Plugson\src\Lib\libhttp\include\civetweb.c - MerlyMentor

1/* Copyright (c) 2013-2016 the Civetweb developers
2 * Copyright (c) 2004-2013 Sergey Lyubka
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to deal
6 * in the Software without restriction, including without limitation the rights
7 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8 * copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
13 *
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
20 * THE SOFTWARE.
21 */
22
23
24#if defined(_WIN32)
25#if !defined(_CRT_SECURE_NO_WARNINGS)
26#define _CRT_SECURE_NO_WARNINGS /* Disable deprecation warning in VS2005 */
27#endif
28#ifndef _WIN32_WINNT /* defined for tdm-gcc so we can use getnameinfo */
29#define _WIN32_WINNT 0x0501
30#endif
31#else
32#if defined(__GNUC__) && !defined(_GNU_SOURCE)
33#define _GNU_SOURCE /* for setgroups() */
34#endif
35#if defined(__linux__) && !defined(_XOPEN_SOURCE)
36#define _XOPEN_SOURCE 600 /* For flockfile() on Linux */
37#endif
38#ifndef _LARGEFILE_SOURCE
39#define _LARGEFILE_SOURCE /* For fseeko(), ftello() */
40#endif
41#ifndef _FILE_OFFSET_BITS
42#define _FILE_OFFSET_BITS 64 /* Use 64-bit file offsets by default */
43#endif
44#ifndef __STDC_FORMAT_MACROS
45#define __STDC_FORMAT_MACROS /* <inttypes.h> wants this for C++ */
46#endif
47#ifndef __STDC_LIMIT_MACROS
48#define __STDC_LIMIT_MACROS /* C++ wants that for INT64_MAX */
49#endif
50#ifdef __sun
51#define __EXTENSIONS__  /* to expose flockfile and friends in stdio.h */
52#define __inline inline /* not recognized on older compiler versions */
53#endif
54#endif
55
56#if defined(USE_LUA) && defined(USE_WEBSOCKET)
57#define USE_TIMERS
58#endif
59
60#if defined(_MSC_VER)
61/* 'type cast' : conversion from 'int' to 'HANDLE' of greater size */
62#pragma warning(disable : 4306)
63/* conditional expression is constant: introduced by FD_SET(..) */
64#pragma warning(disable : 4127)
65/* non-constant aggregate initializer: issued due to missing C99 support */
66#pragma warning(disable : 4204)
67/* padding added after data member */
68#pragma warning(disable : 4820)
69/* not defined as a preprocessor macro, replacing with '0' for '#if/#elif' */
70#pragma warning(disable : 4668)
71/* no function prototype given: converting '()' to '(void)' */
72#pragma warning(disable : 4255)
73/* function has been selected for automatic inline expansion */
74#pragma warning(disable : 4711)
75#endif
76
77
78/* This code uses static_assert to check some conditions.
79 * Unfortunately some compilers still do not support it, so we have a
80 * replacement function here. */
81#if defined(_MSC_VER) && (_MSC_VER >= 1600)
82#define mg_static_assert static_assert
83#elif defined(__cplusplus) && (__cplusplus >= 201103L)
84#define mg_static_assert static_assert
85#elif defined(__STDC_VERSION__) && (__STDC_VERSION__ >= 201112L)
86#define mg_static_assert _Static_assert
87#else
88char static_assert_replacement[1];
89#define mg_static_assert(cond, txt)                                            \
90  extern char static_assert_replacement[(cond) ? 1 : -1]
91#endif
92
93mg_static_assert(sizeof(int) == 4 || sizeof(int) == 8,
94                 "int data type size check");
95mg_static_assert(sizeof(void *) == 4 || sizeof(void *) == 8,
96                 "pointer data type size check");
97mg_static_assert(sizeof(void *) >= sizeof(int), "data type size check");
98/* mg_static_assert(sizeof(size_t) == 4 || sizeof(size_t) == 8, "size_t data
99 * type size check"); */
100
101/* DTL -- including winsock2.h works better if lean and mean */
102#ifndef WIN32_LEAN_AND_MEAN
103#define WIN32_LEAN_AND_MEAN
104#endif
105
106#if defined(__SYMBIAN32__)
107#define NO_SSL /* SSL is not supported */
108#define NO_CGI /* CGI is not supported */
109#define PATH_MAX FILENAME_MAX
110#endif /* __SYMBIAN32__ */
111
112
113/* Include the header file here, so the CivetWeb interface is defined for the
114 * entire implementation, including the following forward definitions. */
115#include "civetweb.h"
116
117
118#ifndef IGNORE_UNUSED_RESULT
119#define IGNORE_UNUSED_RESULT(a) ((void)((a) && 1))
120#endif
121
122#ifndef _WIN32_WCE /* Some ANSI #includes are not available on Windows CE */
123#include <sys/types.h>
124#include <sys/stat.h>
125#include <errno.h>
126#include <signal.h>
127#include <fcntl.h>
128#endif /* !_WIN32_WCE */
129
130#ifdef __MACH__
131
132#define CLOCK_MONOTONIC (1)
133#define CLOCK_REALTIME (2)
134
135#include <sys/time.h>
136#include <mach/clock.h>
137#include <mach/mach.h>
138#include <mach/mach_time.h>
139#include <assert.h>
140
141
142/* clock_gettime is not implemented on OSX */
143int clock_gettime(int clk_id, struct timespec *t);
144
145int
146clock_gettime(int clk_id, struct timespec *t)
147{
148  memset(t, 0, sizeof(*t));
149  if (clk_id == CLOCK_REALTIME) {
150    struct timeval now;
151    int rv = gettimeofday(&now, NULL);
152    if (rv) {
153      return rv;
154    }
155    t->tv_sec = now.tv_sec;
156    t->tv_nsec = now.tv_usec * 1000;
157    return 0;
158
159  } else if (clk_id == CLOCK_MONOTONIC) {
160    static uint64_t clock_start_time = 0;
161    static mach_timebase_info_data_t timebase_ifo = {0, 0};
162
163    uint64_t now = mach_absolute_time();
164
165    if (clock_start_time == 0) {
166      kern_return_t mach_status = mach_timebase_info(&timebase_ifo);
167#if defined(DEBUG)
168      assert(mach_status == KERN_SUCCESS);
169#else
170      /* appease "unused variable" warning for release builds */
171      (void)mach_status;
172#endif
173      clock_start_time = now;
174    }
175
176    now = (uint64_t)((double)(now - clock_start_time)
177                     * (double)timebase_ifo.numer
178                     / (double)timebase_ifo.denom);
179
180    t->tv_sec = now / 1000000000;
181    t->tv_nsec = now % 1000000000;
182    return 0;
183  }
184  return -1; /* EINVAL - Clock ID is unknown */
185}
186#endif
187
188
189#include <time.h>
190#include <stdlib.h>
191#include <stdarg.h>
192#include <assert.h>
193#include <string.h>
194#include <ctype.h>
195#include <limits.h>
196#include <stddef.h>
197#include <stdio.h>
198
199
200#ifndef MAX_WORKER_THREADS
201#define MAX_WORKER_THREADS (1024 * 64)
202#endif
203#ifndef SOCKET_TIMEOUT_QUANTUM
204#define SOCKET_TIMEOUT_QUANTUM (10000)
205#endif
206
207mg_static_assert(MAX_WORKER_THREADS >= 1,
208                 "worker threads must be a positive number");
209
210#if defined(_WIN32)                                                            \
211    && !defined(__SYMBIAN32__) /* WINDOWS / UNIX include block */
212#include <windows.h>
213#include <winsock2.h> /* DTL add for SO_EXCLUSIVE */
214#include <ws2tcpip.h>
215
216typedef const char *SOCK_OPT_TYPE;
217
218#if !defined(PATH_MAX)
219#define PATH_MAX (MAX_PATH)
220#endif
221
222#if !defined(PATH_MAX)
223#define PATH_MAX (4096)
224#endif
225
226mg_static_assert(PATH_MAX >= 1, "path length must be a positive number");
227
228#ifndef _IN_PORT_T
229#ifndef in_port_t
230#define in_port_t u_short
231#endif
232#endif
233
234#ifndef _WIN32_WCE
235#include <process.h>
236#include <direct.h>
237#include <io.h>
238#else          /* _WIN32_WCE */
239#define NO_CGI /* WinCE has no pipes */
240
241typedef long off_t;
242
243#define errno ((int)(GetLastError()))
244#define strerror(x) (_ultoa(x, (char *)_alloca(sizeof(x) * 3), 10))
245#endif /* _WIN32_WCE */
246
247#define MAKEUQUAD(lo, hi)                                                      \
248  ((uint64_t)(((uint32_t)(lo)) | ((uint64_t)((uint32_t)(hi))) << 32))
249#define RATE_DIFF (10000000) /* 100 nsecs */
250#define EPOCH_DIFF (MAKEUQUAD(0xd53e8000, 0x019db1de))
251#define SYS2UNIX_TIME(lo, hi)                                                  \
252  ((time_t)((MAKEUQUAD((lo), (hi)) - EPOCH_DIFF) / RATE_DIFF))
253
254/* Visual Studio 6 does not know __func__ or __FUNCTION__
255 * The rest of MS compilers use __FUNCTION__, not C99 __func__
256 * Also use _strtoui64 on modern M$ compilers */
257#if defined(_MSC_VER)
258#if (_MSC_VER < 1300)
259#define STRX(x) #x
260#define STR(x) STRX(x)
261#define __func__ __FILE__ ":" STR(__LINE__)
262#define strtoull(x, y, z) ((unsigned __int64)_atoi64(x))
263#define strtoll(x, y, z) (_atoi64(x))
264#else
265#define __func__ __FUNCTION__
266#define strtoull(x, y, z) (_strtoui64(x, y, z))
267#define strtoll(x, y, z) (_strtoi64(x, y, z))
268#endif
269#endif /* _MSC_VER */
270
271#define ERRNO ((int)(GetLastError()))
272#define NO_SOCKLEN_T
273
274#if defined(_WIN64) || defined(__MINGW64__)
275#define SSL_LIB "ssleay64.dll"
276#define CRYPTO_LIB "libeay64.dll"
277#else
278#define SSL_LIB "ssleay32.dll"
279#define CRYPTO_LIB "libeay32.dll"
280#endif
281
282#define O_NONBLOCK (0)
283#ifndef W_OK
284#define W_OK (2) /* http://msdn.microsoft.com/en-us/library/1w06ktdy.aspx */
285#endif
286#if !defined(EWOULDBLOCK)
287#define EWOULDBLOCK WSAEWOULDBLOCK
288#endif /* !EWOULDBLOCK */
289#define _POSIX_
290#define INT64_FMT "I64d"
291#define UINT64_FMT "I64u"
292
293#define WINCDECL __cdecl
294#define SHUT_RD (0)
295#define SHUT_WR (1)
296#define SHUT_BOTH (2)
297#define vsnprintf_impl _vsnprintf
298#define access _access
299#define mg_sleep(x) (Sleep(x))
300
301#define pipe(x) _pipe(x, MG_BUF_LEN, _O_BINARY)
302#ifndef popen
303#define popen(x, y) (_popen(x, y))
304#endif
305#ifndef pclose
306#define pclose(x) (_pclose(x))
307#endif
308#define close(x) (_close(x))
309#define dlsym(x, y) (GetProcAddress((HINSTANCE)(x), (y)))
310#define RTLD_LAZY (0)
311#define fseeko(x, y, z) (_lseeki64(_fileno(x), (y), (z)) == -1 ? -1 : 0)
312#define fdopen(x, y) (_fdopen((x), (y)))
313#define write(x, y, z) (_write((x), (y), (unsigned)z))
314#define read(x, y, z) (_read((x), (y), (unsigned)z))
315#define flockfile(x) (EnterCriticalSection(&global_log_file_lock))
316#define funlockfile(x) (LeaveCriticalSection(&global_log_file_lock))
317#define sleep(x) (Sleep((x)*1000))
318#define rmdir(x) (_rmdir(x))
319#define timegm(x) (_mkgmtime(x))
320
321#if !defined(fileno)
322#define fileno(x) (_fileno(x))
323#endif /* !fileno MINGW #defines fileno */
324
325typedef HANDLE pthread_mutex_t;
326typedef DWORD pthread_key_t;
327typedef HANDLE pthread_t;
328typedef struct {
329  CRITICAL_SECTION threadIdSec;
330  int waitingthreadcount;       /* The number of threads queued. */
331  pthread_t *waitingthreadhdls; /* The thread handles. */
332} pthread_cond_t;
333
334#ifndef __clockid_t_defined
335typedef DWORD clockid_t;
336#endif
337#ifndef CLOCK_MONOTONIC
338#define CLOCK_MONOTONIC (1)
339#endif
340#ifndef CLOCK_REALTIME
341#define CLOCK_REALTIME (2)
342#endif
343
344#if defined(_MSC_VER) && (_MSC_VER >= 1900)
345#define _TIMESPEC_DEFINED
346#endif
347#ifndef _TIMESPEC_DEFINED
348struct timespec {
349  time_t tv_sec; /* seconds */
350  long tv_nsec;  /* nanoseconds */
351};
352#endif
353
354#define pid_t HANDLE /* MINGW typedefs pid_t to int. Using #define here. */
355
356static int pthread_mutex_lock(pthread_mutex_t *);
357static int pthread_mutex_unlock(pthread_mutex_t *);
358static void path_to_unicode(const struct mg_connection *conn,
359                            const char *path,
360                            wchar_t *wbuf,
361                            size_t wbuf_len);
362struct file;
363static const char *
364mg_fgets(char *buf, size_t size, struct file *filep, char **p);
365
366
367#if defined(HAVE_STDINT)
368#include <stdint.h>
369#else
370typedef unsigned char uint8_t;
371typedef unsigned short uint16_t;
372typedef unsigned int uint32_t;
373typedef unsigned __int64 uint64_t;
374typedef __int64 int64_t;
375#define INT64_MAX (9223372036854775807)
376#endif /* HAVE_STDINT */
377
378/* POSIX dirent interface */
379struct dirent {
380  char d_name[PATH_MAX];
381};
382
383typedef struct DIR {
384  HANDLE handle;
385  WIN32_FIND_DATAW info;
386  struct dirent result;
387} DIR;
388
389#if defined(_WIN32) && !defined(POLLIN)
390#ifndef HAVE_POLL
391struct pollfd {
392  SOCKET fd;
393  short events;
394  short revents;
395};
396#define POLLIN (0x0300)
397#endif
398#endif
399
400/* Mark required libraries */
401#if defined(_MSC_VER)
402#pragma comment(lib, "Ws2_32.lib")
403#endif
404
405#else /* defined(_WIN32) && !defined(__SYMBIAN32__) - WINDOWS / UNIX include   \
406         block */
407
408#include <sys/wait.h>
409#include <sys/socket.h>
410#include <sys/poll.h>
411#include <netinet/in.h>
412#include <arpa/inet.h>
413#include <sys/time.h>
414#include <sys/utsname.h>
415#include <stdint.h>
416#include <inttypes.h>
417#include <netdb.h>
418#include <netinet/tcp.h>
419typedef const void *SOCK_OPT_TYPE;
420
421#if defined(ANDROID)
422typedef unsigned short int in_port_t;
423#endif
424
425#include <pwd.h>
426#include <unistd.h>
427#include <grp.h>
428#include <dirent.h>
429#define vsnprintf_impl vsnprintf
430
431#if !defined(NO_SSL_DL) && !defined(NO_SSL)
432#include <dlfcn.h>
433#endif
434#include <pthread.h>
435#if defined(__MACH__)
436#define SSL_LIB "libssl.dylib"
437#define CRYPTO_LIB "libcrypto.dylib"
438#else
439#if !defined(SSL_LIB)
440#define SSL_LIB "libssl.so"
441#endif
442#if !defined(CRYPTO_LIB)
443#define CRYPTO_LIB "libcrypto.so"
444#endif
445#endif
446#ifndef O_BINARY
447#define O_BINARY (0)
448#endif /* O_BINARY */
449#define closesocket(a) (close(a))
450#define mg_mkdir(conn, path, mode) (mkdir(path, mode))
451#define mg_remove(conn, x) (remove(x))
452#define mg_sleep(x) (usleep((x)*1000))
453#define mg_opendir(conn, x) (opendir(x))
454#define mg_closedir(x) (closedir(x))
455#define mg_readdir(x) (readdir(x))
456#define ERRNO (errno)
457#define INVALID_SOCKET (-1)
458#define INT64_FMT PRId64
459#define UINT64_FMT PRIu64
460typedef int SOCKET;
461#define WINCDECL
462
463#if defined(__hpux)
464/* HPUX 11 does not have monotonic, fall back to realtime */
465#ifndef CLOCK_MONOTONIC
466#define CLOCK_MONOTONIC CLOCK_REALTIME
467#endif
468
469/* HPUX defines socklen_t incorrectly as size_t which is 64bit on
470 * Itanium.  Without defining _XOPEN_SOURCE or _XOPEN_SOURCE_EXTENDED
471 * the prototypes use int* rather than socklen_t* which matches the
472 * actual library expectation.  When called with the wrong size arg
473 * accept() returns a zero client inet addr and check_acl() always
474 * fails.  Since socklen_t is widely used below, just force replace
475 * their typedef with int. - DTL
476 */
477#define socklen_t int
478#endif /* hpux */
479
480#endif /* defined(_WIN32) && !defined(__SYMBIAN32__) - WINDOWS / UNIX include  \
481          block */
482
483/* va_copy should always be a macro, C99 and C++11 - DTL */
484#ifndef va_copy
485#define va_copy(x, y) ((x) = (y))
486#endif
487
488#ifdef _WIN32
489/* Create substitutes for POSIX functions in Win32. */
490
491#if defined(__MINGW32__)
492/* Show no warning in case system functions are not used. */
493#pragma GCC diagnostic push
494#pragma GCC diagnostic ignored "-Wunused-function"
495#endif
496
497
498static CRITICAL_SECTION global_log_file_lock;
499static DWORD
500pthread_self(void)
501{
502  return GetCurrentThreadId();
503}
504
505
506static int
507pthread_key_create(
508    pthread_key_t *key,
509    void (*_ignored)(void *) /* destructor not supported for Windows */
510    )
511{
512  (void)_ignored;
513
514  if ((key != 0)) {
515    *key = TlsAlloc();
516    return (*key != TLS_OUT_OF_INDEXES) ? 0 : -1;
517  }
518  return -2;
519}
520
521
522static int
523pthread_key_delete(pthread_key_t key)
524{
525  return TlsFree(key) ? 0 : 1;
526}
527
528
529static int
530pthread_setspecific(pthread_key_t key, void *value)
531{
532  return TlsSetValue(key, value) ? 0 : 1;
533}
534
535
536static void *
537pthread_getspecific(pthread_key_t key)
538{
539  return TlsGetValue(key);
540}
541
542#if defined(__MINGW32__)
543/* Enable unused function warning again */
544#pragma GCC diagnostic pop
545#endif
546
547static struct pthread_mutex_undefined_struct *pthread_mutex_attr = NULL;
548#else
549static pthread_mutexattr_t pthread_mutex_attr;
550#endif /* _WIN32 */
551
552
553#define PASSWORDS_FILE_NAME ".htpasswd"
554#define CGI_ENVIRONMENT_SIZE (4096)
555#define MAX_CGI_ENVIR_VARS (256)
556#define MG_BUF_LEN (8192)
557
558#ifndef MAX_REQUEST_SIZE
559#define MAX_REQUEST_SIZE (16384)
560#endif
561
562mg_static_assert(MAX_REQUEST_SIZE >= 256,
563                 "request size length must be a positive number");
564
565#define ARRAY_SIZE(array) (sizeof(array) / sizeof(array[0]))
566
567#if !defined(DEBUG_TRACE)
568#if defined(DEBUG)
569
570
571static void DEBUG_TRACE_FUNC(const char *func,
572                             unsigned line,
573                             PRINTF_FORMAT_STRING(const char *fmt),
574                             ...) PRINTF_ARGS(3, 4);
575
576static void
577DEBUG_TRACE_FUNC(const char *func, unsigned line, const char *fmt, ...)
578{
579  va_list args;
580  flockfile(stdout);
581  printf("*** %lu.%p.%s.%u: ",
582         (unsigned long)time(NULL),
583         (void *)pthread_self(),
584         func,
585         line);
586  va_start(args, fmt);
587  vprintf(fmt, args);
588  va_end(args);
589  putchar('\n');
590  fflush(stdout);
591  funlockfile(stdout);
592}
593
594#define DEBUG_TRACE(fmt, ...)                                                  \
595  DEBUG_TRACE_FUNC(__func__, __LINE__, fmt, __VA_ARGS__)
596
597#else
598#define DEBUG_TRACE(fmt, ...)                                                  \
599  do {                                                                       \
600  } while (0)
601#endif /* DEBUG */
602#endif /* DEBUG_TRACE */
603
604#if defined(MEMORY_DEBUGGING)
605unsigned long mg_memory_debug_blockCount = 0;
606unsigned long mg_memory_debug_totalMemUsed = 0;
607
608
609static void *
610mg_malloc_ex(size_t size, const char *file, unsigned line)
611{
612  void *data = malloc(size + sizeof(size_t));
613  void *memory = 0;
614  char mallocStr[256];
615
616  if (data) {
617    *(size_t *)data = size;
618    mg_memory_debug_totalMemUsed += size;
619    mg_memory_debug_blockCount++;
620    memory = (void *)(((char *)data) + sizeof(size_t));
621  }
622
623  sprintf(mallocStr,
624          "MEM: %p %5lu alloc   %7lu %4lu --- %s:%u\n",
625          memory,
626          (unsigned long)size,
627          mg_memory_debug_totalMemUsed,
628          mg_memory_debug_blockCount,
629          file,
630          line);
631#if defined(_WIN32)
632  OutputDebugStringA(mallocStr);
633#else
634  DEBUG_TRACE("%s", mallocStr);
635#endif
636
637  return memory;
638}
639
640
641static void *
642mg_calloc_ex(size_t count, size_t size, const char *file, unsigned line)
643{
644  void *data = mg_malloc_ex(size * count, file, line);
645  if (data) {
646    memset(data, 0, size);
647  }
648  return data;
649}
650
651
652static void
653mg_free_ex(void *memory, const char *file, unsigned line)
654{
655  char mallocStr[256];
656  void *data = (void *)(((char *)memory) - sizeof(size_t));
657  size_t size;
658
659  if (memory) {
660    size = *(size_t *)data;
661    mg_memory_debug_totalMemUsed -= size;
662    mg_memory_debug_blockCount--;
663    sprintf(mallocStr,
664            "MEM: %p %5lu free    %7lu %4lu --- %s:%u\n",
665            memory,
666            (unsigned long)size,
667            mg_memory_debug_totalMemUsed,
668            mg_memory_debug_blockCount,
669            file,
670            line);
671#if defined(_WIN32)
672    OutputDebugStringA(mallocStr);
673#else
674    DEBUG_TRACE("%s", mallocStr);
675#endif
676
677    free(data);
678  }
679}
680
681
682static void *
683mg_realloc_ex(void *memory, size_t newsize, const char *file, unsigned line)
684{
685  char mallocStr[256];
686  void *data;
687  void *_realloc;
688  size_t oldsize;
689
690  if (newsize) {
691    if (memory) {
692      data = (void *)(((char *)memory) - sizeof(size_t));
693      oldsize = *(size_t *)data;
694      _realloc = realloc(data, newsize + sizeof(size_t));
695      if (_realloc) {
696        data = _realloc;
697        mg_memory_debug_totalMemUsed -= oldsize;
698        sprintf(mallocStr,
699                "MEM: %p %5lu r-free  %7lu %4lu --- %s:%u\n",
700                memory,
701                (unsigned long)oldsize,
702                mg_memory_debug_totalMemUsed,
703                mg_memory_debug_blockCount,
704                file,
705                line);
706#if defined(_WIN32)
707        OutputDebugStringA(mallocStr);
708#else
709        DEBUG_TRACE("%s", mallocStr);
710#endif
711        mg_memory_debug_totalMemUsed += newsize;
712        sprintf(mallocStr,
713                "MEM: %p %5lu r-alloc %7lu %4lu --- %s:%u\n",
714                memory,
715                (unsigned long)newsize,
716                mg_memory_debug_totalMemUsed,
717                mg_memory_debug_blockCount,
718                file,
719                line);
720#if defined(_WIN32)
721        OutputDebugStringA(mallocStr);
722#else
723        DEBUG_TRACE("%s", mallocStr);
724#endif
725        *(size_t *)data = newsize;
726        data = (void *)(((char *)data) + sizeof(size_t));
727      } else {
728#if defined(_WIN32)
729        OutputDebugStringA("MEM: realloc failed\n");
730#else
731        DEBUG_TRACE("%s", "MEM: realloc failed\n");
732#endif
733        return _realloc;
734      }
735    } else {
736      data = mg_malloc_ex(newsize, file, line);
737    }
738  } else {
739    data = 0;
740    mg_free_ex(memory, file, line);
741  }
742
743  return data;
744}
745
746#define mg_malloc(a) mg_malloc_ex(a, __FILE__, __LINE__)
747#define mg_calloc(a, b) mg_calloc_ex(a, b, __FILE__, __LINE__)
748#define mg_realloc(a, b) mg_realloc_ex(a, b, __FILE__, __LINE__)
749#define mg_free(a) mg_free_ex(a, __FILE__, __LINE__)
750
751#else
752
753static __inline void *
754mg_malloc(size_t a)
755{
756  return malloc(a);
757}
758
759static __inline void *
760mg_calloc(size_t a, size_t b)
761{
762  return calloc(a, b);
763}
764
765static __inline void *
766mg_realloc(void *a, size_t b)
767{
768  return realloc(a, b);
769}
770
771static __inline void
772mg_free(void *a)
773{
774  free(a);
775}
776
777#endif
778
779
780static void mg_vsnprintf(const struct mg_connection *conn,
781                         int *truncated,
782                         char *buf,
783                         size_t buflen,
784                         const char *fmt,
785                         va_list ap);
786
787static void mg_snprintf(const struct mg_connection *conn,
788                        int *truncated,
789                        char *buf,
790                        size_t buflen,
791                        PRINTF_FORMAT_STRING(const char *fmt),
792                        ...) PRINTF_ARGS(5, 6);
793
794/* This following lines are just meant as a reminder to use the mg-functions
795 * for memory management */
796#ifdef malloc
797#undef malloc
798#endif
799#ifdef calloc
800#undef calloc
801#endif
802#ifdef realloc
803#undef realloc
804#endif
805#ifdef free
806#undef free
807#endif
808#ifdef snprintf
809#undef snprintf
810#endif
811#ifdef vsnprintf
812#undef vsnprintf
813#endif
814#define malloc DO_NOT_USE_THIS_FUNCTION__USE_mg_malloc
815#define calloc DO_NOT_USE_THIS_FUNCTION__USE_mg_calloc
816#define realloc DO_NOT_USE_THIS_FUNCTION__USE_mg_realloc
817#define free DO_NOT_USE_THIS_FUNCTION__USE_mg_free
818#define snprintf DO_NOT_USE_THIS_FUNCTION__USE_mg_snprintf
819#ifdef _WIN32 /* vsnprintf must not be used in any system, *                   \
820               * but this define only works well for Windows. */
821#define vsnprintf DO_NOT_USE_THIS_FUNCTION__USE_mg_vsnprintf
822#endif
823
824#define MD5_STATIC static
825#include "md5.inl"
826
827/* Darwin prior to 7.0 and Win32 do not have socklen_t */
828#ifdef NO_SOCKLEN_T
829typedef int socklen_t;
830#endif /* NO_SOCKLEN_T */
831#define _DARWIN_UNLIMITED_SELECT
832
833#define IP_ADDR_STR_LEN (50) /* IPv6 hex string is 46 chars */
834
835#if !defined(MSG_NOSIGNAL)
836#define MSG_NOSIGNAL (0)
837#endif
838
839#if !defined(SOMAXCONN)
840#define SOMAXCONN (100)
841#endif
842
843/* Size of the accepted socket queue */
844#if !defined(MGSQLEN)
845#define MGSQLEN (20)
846#endif
847
848#if defined(NO_SSL_DL)
849#include <openssl/ssl.h>
850#include <openssl/err.h>
851#include <openssl/crypto.h>
852#include <openssl/x509.h>
853#include <openssl/pem.h>
854#else
855/* SSL loaded dynamically from DLL.
856 * I put the prototypes here to be independent from OpenSSL source
857 * installation. */
858
859typedef struct ssl_st SSL;
860typedef struct ssl_method_st SSL_METHOD;
861typedef struct ssl_ctx_st SSL_CTX;
862typedef struct x509_store_ctx_st X509_STORE_CTX;
863
864#define SSL_CTRL_OPTIONS (32)
865#define SSL_CTRL_CLEAR_OPTIONS (77)
866#define SSL_CTRL_SET_ECDH_AUTO (94)
867
868#define SSL_VERIFY_NONE (0)
869#define SSL_VERIFY_PEER (1)
870#define SSL_VERIFY_FAIL_IF_NO_PEER_CERT (2)
871#define SSL_VERIFY_CLIENT_ONCE (4)
872#define SSL_OP_ALL ((long)(0x80000BFFUL))
873#define SSL_OP_NO_SSLv2 (0x01000000L)
874#define SSL_OP_NO_SSLv3 (0x02000000L)
875#define SSL_OP_NO_TLSv1 (0x04000000L)
876#define SSL_OP_NO_TLSv1_2 (0x08000000L)
877#define SSL_OP_NO_TLSv1_1 (0x10000000L)
878#define SSL_OP_SINGLE_DH_USE (0x00100000L)
879
880struct ssl_func {
881  const char *name;  /* SSL function name */
882  void (*ptr)(void); /* Function pointer */
883};
884
885#define SSL_free (*(void (*)(SSL *))ssl_sw[0].ptr)
886#define SSL_accept (*(int (*)(SSL *))ssl_sw[1].ptr)
887#define SSL_connect (*(int (*)(SSL *))ssl_sw[2].ptr)
888#define SSL_read (*(int (*)(SSL *, void *, int))ssl_sw[3].ptr)
889#define SSL_write (*(int (*)(SSL *, const void *, int))ssl_sw[4].ptr)
890#define SSL_get_error (*(int (*)(SSL *, int))ssl_sw[5].ptr)
891#define SSL_set_fd (*(int (*)(SSL *, SOCKET))ssl_sw[6].ptr)
892#define SSL_new (*(SSL * (*)(SSL_CTX *))ssl_sw[7].ptr)
893#define SSL_CTX_new (*(SSL_CTX * (*)(SSL_METHOD *))ssl_sw[8].ptr)
894#define SSLv23_server_method (*(SSL_METHOD * (*)(void))ssl_sw[9].ptr)
895#define SSL_library_init (*(int (*)(void))ssl_sw[10].ptr)
896#define SSL_CTX_use_PrivateKey_file                                            \
897  (*(int (*)(SSL_CTX *, const char *, int))ssl_sw[11].ptr)
898#define SSL_CTX_use_certificate_file                                           \
899  (*(int (*)(SSL_CTX *, const char *, int))ssl_sw[12].ptr)
900#define SSL_CTX_set_default_passwd_cb                                          \
901  (*(void (*)(SSL_CTX *, mg_callback_t))ssl_sw[13].ptr)
902#define SSL_CTX_free (*(void (*)(SSL_CTX *))ssl_sw[14].ptr)
903#define SSL_load_error_strings (*(void (*)(void))ssl_sw[15].ptr)
904#define SSL_CTX_use_certificate_chain_file                                     \
905  (*(int (*)(SSL_CTX *, const char *))ssl_sw[16].ptr)
906#define SSLv23_client_method (*(SSL_METHOD * (*)(void))ssl_sw[17].ptr)
907#define SSL_pending (*(int (*)(SSL *))ssl_sw[18].ptr)
908#define SSL_CTX_set_verify                                                     \
909  (*(void (*)(SSL_CTX *,                                                     \
910              int,                                                           \
911              int (*verify_callback)(int, X509_STORE_CTX *)))ssl_sw[19].ptr)
912#define SSL_shutdown (*(int (*)(SSL *))ssl_sw[20].ptr)
913#define SSL_CTX_load_verify_locations                                          \
914  (*(int (*)(SSL_CTX *, const char *, const char *))ssl_sw[21].ptr)
915#define SSL_CTX_set_default_verify_paths (*(int (*)(SSL_CTX *))ssl_sw[22].ptr)
916#define SSL_CTX_set_verify_depth (*(void (*)(SSL_CTX *, int))ssl_sw[23].ptr)
917#define SSL_get_peer_certificate (*(X509 * (*)(SSL *))ssl_sw[24].ptr)
918#define SSL_get_version (*(const char *(*)(SSL *))ssl_sw[25].ptr)
919#define SSL_get_current_cipher (*(SSL_CIPHER * (*)(SSL *))ssl_sw[26].ptr)
920#define SSL_CIPHER_get_name                                                    \
921  (*(const char *(*)(const SSL_CIPHER *))ssl_sw[27].ptr)
922#define SSL_CTX_check_private_key (*(int (*)(SSL_CTX *))ssl_sw[28].ptr)
923#define SSL_CTX_set_session_id_context                                         \
924  (*(int (*)(SSL_CTX *, const unsigned char *, unsigned int))ssl_sw[29].ptr)
925#define SSL_CTX_ctrl (*(long (*)(SSL_CTX *, int, long, void *))ssl_sw[30].ptr)
926#define SSL_CTX_set_cipher_list                                                \
927  (*(int (*)(SSL_CTX *, const char *))ssl_sw[31].ptr)
928#define SSL_CTX_set_options(ctx, op)                                           \
929  SSL_CTX_ctrl((ctx), SSL_CTRL_OPTIONS, (op), NULL)
930#define SSL_CTX_clear_options(ctx, op)                                         \
931  SSL_CTX_ctrl((ctx), SSL_CTRL_CLEAR_OPTIONS, (op), NULL)
932#define SSL_CTX_set_ecdh_auto(ctx, onoff)                                      \
933  SSL_CTX_ctrl(ctx, SSL_CTRL_SET_ECDH_AUTO, onoff, NULL)
934
935#define CRYPTO_num_locks (*(int (*)(void))crypto_sw[0].ptr)
936#define CRYPTO_set_locking_callback                                            \
937  (*(void (*)(void (*)(int, int, const char *, int)))crypto_sw[1].ptr)
938#define CRYPTO_set_id_callback                                                 \
939  (*(void (*)(unsigned long (*)(void)))crypto_sw[2].ptr)
940#define ERR_get_error (*(unsigned long (*)(void))crypto_sw[3].ptr)
941#define ERR_error_string (*(char *(*)(unsigned long, char *))crypto_sw[4].ptr)
942#define ERR_remove_state (*(void (*)(unsigned long))crypto_sw[5].ptr)
943#define ERR_free_strings (*(void (*)(void))crypto_sw[6].ptr)
944#define ENGINE_cleanup (*(void (*)(void))crypto_sw[7].ptr)
945#define CONF_modules_unload (*(void (*)(int))crypto_sw[8].ptr)
946#define CRYPTO_cleanup_all_ex_data (*(void (*)(void))crypto_sw[9].ptr)
947#define EVP_cleanup (*(void (*)(void))crypto_sw[10].ptr)
948
949
950/* set_ssl_option() function updates this array.
951 * It loads SSL library dynamically and changes NULLs to the actual addresses
952 * of respective functions. The macros above (like SSL_connect()) are really
953 * just calling these functions indirectly via the pointer. */
954static struct ssl_func ssl_sw[] = {{"SSL_free", NULL},
955                                   {"SSL_accept", NULL},
956                                   {"SSL_connect", NULL},
957                                   {"SSL_read", NULL},
958                                   {"SSL_write", NULL},
959                                   {"SSL_get_error", NULL},
960                                   {"SSL_set_fd", NULL},
961                                   {"SSL_new", NULL},
962                                   {"SSL_CTX_new", NULL},
963                                   {"SSLv23_server_method", NULL},
964                                   {"SSL_library_init", NULL},
965                                   {"SSL_CTX_use_PrivateKey_file", NULL},
966                                   {"SSL_CTX_use_certificate_file", NULL},
967                                   {"SSL_CTX_set_default_passwd_cb", NULL},
968                                   {"SSL_CTX_free", NULL},
969                                   {"SSL_load_error_strings", NULL},
970                                   {"SSL_CTX_use_certificate_chain_file", NULL},
971                                   {"SSLv23_client_method", NULL},
972                                   {"SSL_pending", NULL},
973                                   {"SSL_CTX_set_verify", NULL},
974                                   {"SSL_shutdown", NULL},
975                                   {"SSL_CTX_load_verify_locations", NULL},
976                                   {"SSL_CTX_set_default_verify_paths", NULL},
977                                   {"SSL_CTX_set_verify_depth", NULL},
978                                   {"SSL_get_peer_certificate", NULL},
979                                   {"SSL_get_version", NULL},
980                                   {"SSL_get_current_cipher", NULL},
981                                   {"SSL_CIPHER_get_name", NULL},
982                                   {"SSL_CTX_check_private_key", NULL},
983                                   {"SSL_CTX_set_session_id_context", NULL},
984                                   {"SSL_CTX_ctrl", NULL},
985                                   {"SSL_CTX_set_cipher_list", NULL},
986                                   {NULL, NULL}};
987
988
989/* Similar array as ssl_sw. These functions could be located in different
990 * lib. */
991#if !defined(NO_SSL)
992static struct ssl_func crypto_sw[] = {{"CRYPTO_num_locks", NULL},
993                                      {"CRYPTO_set_locking_callback", NULL},
994                                      {"CRYPTO_set_id_callback", NULL},
995                                      {"ERR_get_error", NULL},
996                                      {"ERR_error_string", NULL},
997                                      {"ERR_remove_state", NULL},
998                                      {"ERR_free_strings", NULL},
999                                      {"ENGINE_cleanup", NULL},
1000                                      {"CONF_modules_unload", NULL},
1001                                      {"CRYPTO_cleanup_all_ex_data", NULL},
1002                                      {"EVP_cleanup", NULL},
1003                                      {NULL, NULL}};
1004#endif /* NO_SSL */
1005#endif /* NO_SSL_DL */
1006
1007
1008#if !defined(NO_CACHING)
1009static const char *month_names[] = {"Jan",
1010                                    "Feb",
1011                                    "Mar",
1012                                    "Apr",
1013                                    "May",
1014                                    "Jun",
1015                                    "Jul",
1016                                    "Aug",
1017                                    "Sep",
1018                                    "Oct",
1019                                    "Nov",
1020                                    "Dec"};
1021#endif /* !NO_CACHING */
1022
1023/* Unified socket address. For IPv6 support, add IPv6 address structure in the
1024 * union u. */
1025union usa {
1026  struct sockaddr sa;
1027  struct sockaddr_in sin;
1028#if defined(USE_IPV6)
1029  struct sockaddr_in6 sin6;
1030#endif
1031};
1032
1033/* Describes a string (chunk of memory). */
1034struct vec {
1035  const char *ptr;
1036  size_t len;
1037};
1038
1039struct file {
1040  uint64_t size;
1041  time_t last_modified;
1042  FILE *fp;
1043  const char *membuf; /* Non-NULL if file data is in memory */
1044  int is_directory;
1045  int gzipped; /* set to 1 if the content is gzipped
1046                * in which case we need a content-encoding: gzip header */
1047};
1048
1049#define STRUCT_FILE_INITIALIZER                                                \
1050  {                                                                          \
1051    (uint64_t)0, (time_t)0, (FILE *)NULL, (const char *)NULL, 0, 0         \
1052  }
1053
1054/* Describes listening socket, or socket which was accept()-ed by the master
1055 * thread and queued for future handling by the worker thread. */
1056struct socket {
1057  SOCKET sock;             /* Listening socket */
1058  union usa lsa;           /* Local socket address */
1059  union usa rsa;           /* Remote socket address */
1060  unsigned char is_ssl;    /* Is port SSL-ed */
1061  unsigned char ssl_redir; /* Is port supposed to redirect everything to SSL
1062                            * port */
1063};
1064
1065/* NOTE(lsm): this enum shoulds be in sync with the config_options below. */
1066enum {
1067  CGI_EXTENSIONS,
1068  CGI_ENVIRONMENT,
1069  PUT_DELETE_PASSWORDS_FILE,
1070  CGI_INTERPRETER,
1071  PROTECT_URI,
1072  AUTHENTICATION_DOMAIN,
1073  SSI_EXTENSIONS,
1074  THROTTLE,
1075  ACCESS_LOG_FILE,
1076  ENABLE_DIRECTORY_LISTING,
1077  ERROR_LOG_FILE,
1078  GLOBAL_PASSWORDS_FILE,
1079  INDEX_FILES,
1080  ENABLE_KEEP_ALIVE,
1081  ACCESS_CONTROL_LIST,
1082  EXTRA_MIME_TYPES,
1083  LISTENING_PORTS,
1084  DOCUMENT_ROOT,
1085  SSL_CERTIFICATE,
1086  NUM_THREADS,
1087  RUN_AS_USER,
1088  REWRITE,
1089  HIDE_FILES,
1090  REQUEST_TIMEOUT,
1091  SSL_DO_VERIFY_PEER,
1092  SSL_CA_PATH,
1093  SSL_CA_FILE,
1094  SSL_VERIFY_DEPTH,
1095  SSL_DEFAULT_VERIFY_PATHS,
1096  SSL_CIPHER_LIST,
1097  SSL_PROTOCOL_VERSION,
1098  SSL_SHORT_TRUST,
1099#if defined(USE_WEBSOCKET)
1100  WEBSOCKET_TIMEOUT,
1101#endif
1102  DECODE_URL,
1103
1104#if defined(USE_LUA)
1105  LUA_PRELOAD_FILE,
1106  LUA_SCRIPT_EXTENSIONS,
1107  LUA_SERVER_PAGE_EXTENSIONS,
1108#endif
1109#if defined(USE_DUKTAPE)
1110  DUKTAPE_SCRIPT_EXTENSIONS,
1111#endif
1112
1113#if defined(USE_WEBSOCKET)
1114  WEBSOCKET_ROOT,
1115#endif
1116#if defined(USE_LUA) && defined(USE_WEBSOCKET)
1117  LUA_WEBSOCKET_EXTENSIONS,
1118#endif
1119  ACCESS_CONTROL_ALLOW_ORIGIN,
1120  ERROR_PAGES,
1121  CONFIG_TCP_NODELAY, /* Prepended CONFIG_ to avoid conflict with the
1122                         * socket option typedef TCP_NODELAY. */
1123#if !defined(NO_CACHING)
1124  STATIC_FILE_MAX_AGE,
1125#endif
1126
1127  NUM_OPTIONS
1128};
1129
1130
1131/* Config option name, config types, default value */
1132static struct mg_option config_options[] = {
1133    {"cgi_pattern", CONFIG_TYPE_EXT_PATTERN, "**.cgi$|**.pl$|**.php$"},
1134    {"cgi_environment", CONFIG_TYPE_STRING, NULL},
1135    {"put_delete_auth_file", CONFIG_TYPE_FILE, NULL},
1136    {"cgi_interpreter", CONFIG_TYPE_FILE, NULL},
1137    {"protect_uri", CONFIG_TYPE_STRING, NULL},
1138    {"authentication_domain", CONFIG_TYPE_STRING, "mydomain.com"},
1139    {"ssi_pattern", CONFIG_TYPE_EXT_PATTERN, "**.shtml$|**.shtm$"},
1140    {"throttle", CONFIG_TYPE_STRING, NULL},
1141    {"access_log_file", CONFIG_TYPE_FILE, NULL},
1142    {"enable_directory_listing", CONFIG_TYPE_BOOLEAN, "yes"},
1143    {"error_log_file", CONFIG_TYPE_FILE, NULL},
1144    {"global_auth_file", CONFIG_TYPE_FILE, NULL},
1145    {"index_files",
1146     CONFIG_TYPE_STRING,
1147#ifdef USE_LUA
1148     "index.xhtml,index.html,index.htm,index.lp,index.lsp,index.lua,index.cgi,"
1149     "index.shtml,index.php"},
1150#else
1151     "index.xhtml,index.html,index.htm,index.cgi,index.shtml,index.php"},
1152#endif
1153    {"enable_keep_alive", CONFIG_TYPE_BOOLEAN, "no"},
1154    {"access_control_list", CONFIG_TYPE_STRING, NULL},
1155    {"extra_mime_types", CONFIG_TYPE_STRING, NULL},
1156    {"listening_ports", CONFIG_TYPE_STRING, "8080"},
1157    {"document_root", CONFIG_TYPE_DIRECTORY, NULL},
1158    {"ssl_certificate", CONFIG_TYPE_FILE, NULL},
1159    {"num_threads", CONFIG_TYPE_NUMBER, "50"},
1160    {"run_as_user", CONFIG_TYPE_STRING, NULL},
1161    {"url_rewrite_patterns", CONFIG_TYPE_STRING, NULL},
1162    {"hide_files_patterns", CONFIG_TYPE_EXT_PATTERN, NULL},
1163    {"request_timeout_ms", CONFIG_TYPE_NUMBER, "30000"},
1164    {"ssl_verify_peer", CONFIG_TYPE_BOOLEAN, "no"},
1165    {"ssl_ca_path", CONFIG_TYPE_DIRECTORY, NULL},
1166    {"ssl_ca_file", CONFIG_TYPE_FILE, NULL},
1167    {"ssl_verify_depth", CONFIG_TYPE_NUMBER, "9"},
1168    {"ssl_default_verify_paths", CONFIG_TYPE_BOOLEAN, "yes"},
1169    {"ssl_cipher_list", CONFIG_TYPE_STRING, NULL},
1170    {"ssl_protocol_version", CONFIG_TYPE_NUMBER, "0"},
1171    {"ssl_short_trust", CONFIG_TYPE_BOOLEAN, "no"},
1172#if defined(USE_WEBSOCKET)
1173    {"websocket_timeout_ms", CONFIG_TYPE_NUMBER, "30000"},
1174#endif
1175    {"decode_url", CONFIG_TYPE_BOOLEAN, "yes"},
1176
1177#if defined(USE_LUA)
1178    {"lua_preload_file", CONFIG_TYPE_FILE, NULL},
1179    {"lua_script_pattern", CONFIG_TYPE_EXT_PATTERN, "**.lua$"},
1180    {"lua_server_page_pattern", CONFIG_TYPE_EXT_PATTERN, "**.lp$|**.lsp$"},
1181#endif
1182#if defined(USE_DUKTAPE)
1183    /* The support for duktape is still in alpha version state.
1184     * The name of this config option might change. */
1185    {"duktape_script_pattern", CONFIG_TYPE_EXT_PATTERN, "**.ssjs$"},
1186#endif
1187
1188#if defined(USE_WEBSOCKET)
1189    {"websocket_root", CONFIG_TYPE_DIRECTORY, NULL},
1190#endif
1191#if defined(USE_LUA) && defined(USE_WEBSOCKET)
1192    {"lua_websocket_pattern", CONFIG_TYPE_EXT_PATTERN, "**.lua$"},
1193#endif
1194    {"access_control_allow_origin", CONFIG_TYPE_STRING, "*"},
1195    {"error_pages", CONFIG_TYPE_DIRECTORY, NULL},
1196    {"tcp_nodelay", CONFIG_TYPE_NUMBER, "0"},
1197#if !defined(NO_CACHING)
1198    {"static_file_max_age", CONFIG_TYPE_NUMBER, "3600"},
1199#endif
1200
1201    {NULL, CONFIG_TYPE_UNKNOWN, NULL}};
1202
1203/* Check if the config_options and the corresponding enum have compatible
1204 * sizes. */
1205mg_static_assert((sizeof(config_options) / sizeof(config_options[0]))
1206                     == (NUM_OPTIONS + 1),
1207                 "config_options and enum not sync");
1208
1209enum { REQUEST_HANDLER, WEBSOCKET_HANDLER, AUTH_HANDLER };
1210
1211struct mg_handler_info {
1212  /* Name/Pattern of the URI. */
1213  char *uri;
1214  size_t uri_len;
1215
1216  /* handler type */
1217  int handler_type;
1218
1219  /* Handler for http/https or authorization requests. */
1220  mg_request_handler handler;
1221
1222  /* Handler for ws/wss (websocket) requests. */
1223  mg_websocket_connect_handler connect_handler;
1224  mg_websocket_ready_handler ready_handler;
1225  mg_websocket_data_handler data_handler;
1226  mg_websocket_close_handler close_handler;
1227
1228  /* Handler for authorization requests */
1229  mg_authorization_handler auth_handler;
1230
1231  /* User supplied argument for the handler function. */
1232  void *cbdata;
1233
1234  /* next handler in a linked list */
1235  struct mg_handler_info *next;
1236};
1237
1238struct mg_context {
1239  volatile int stop_flag;        /* Should we stop event loop */
1240  SSL_CTX *ssl_ctx;              /* SSL context */
1241  char *config[NUM_OPTIONS];     /* Civetweb configuration parameters */
1242  struct mg_callbacks callbacks; /* User-defined callback function */
1243  void *user_data;               /* User-defined data */
1244  int context_type;              /* 1 = server context, 2 = client context */
1245
1246  struct socket *listening_sockets;
1247  in_port_t *listening_ports;
1248  unsigned int num_listening_sockets;
1249
1250  volatile int
1251      running_worker_threads; /* Number of currently running worker threads */
1252  pthread_mutex_t thread_mutex; /* Protects (max|num)_threads */
1253  pthread_cond_t thread_cond; /* Condvar for tracking workers terminations */
1254
1255  struct socket queue[MGSQLEN]; /* Accepted sockets */
1256  volatile int sq_head;         /* Head of the socket queue */
1257  volatile int sq_tail;         /* Tail of the socket queue */
1258  pthread_cond_t sq_full;       /* Signaled when socket is produced */
1259  pthread_cond_t sq_empty;      /* Signaled when socket is consumed */
1260  pthread_t masterthreadid;     /* The master thread ID */
1261  unsigned int
1262      cfg_worker_threads;     /* The number of configured worker threads. */
1263  pthread_t *workerthreadids; /* The worker thread IDs */
1264
1265  time_t start_time;        /* Server start time, used for authentication */
1266  uint64_t auth_nonce_mask; /* Mask for all nonce values */
1267  pthread_mutex_t nonce_mutex; /* Protects nonce_count */
1268  unsigned long nonce_count;   /* Used nonces, used for authentication */
1269
1270  char *systemName; /* What operating system is running */
1271
1272  /* linked list of uri handlers */
1273  struct mg_handler_info *handlers;
1274
1275#if defined(USE_LUA) && defined(USE_WEBSOCKET)
1276  /* linked list of shared lua websockets */
1277  struct mg_shared_lua_websocket_list *shared_lua_websockets;
1278#endif
1279
1280#ifdef USE_TIMERS
1281  struct ttimers *timers;
1282#endif
1283};
1284
1285
1286struct mg_connection {
1287  struct mg_request_info request_info;
1288  struct mg_context *ctx;
1289  SSL *ssl;                 /* SSL descriptor */
1290  SSL_CTX *client_ssl_ctx;  /* SSL context for client connections */
1291  struct socket client;     /* Connected client */
1292  time_t conn_birth_time;   /* Time (wall clock) when connection was
1293                             * established */
1294  struct timespec req_time; /* Time (since system start) when the request
1295                             * was received */
1296  int64_t num_bytes_sent;   /* Total bytes sent to client */
1297  int64_t content_len;      /* Content-Length header value */
1298  int64_t consumed_content; /* How many bytes of content have been read */
1299  int is_chunked;           /* Transfer-Encoding is chunked: 0=no, 1=yes:
1300                             * data available, 2: all data read */
1301  size_t chunk_remainder;   /* Unread data from the last chunk */
1302  char *buf;                /* Buffer for received data */
1303  char *path_info;          /* PATH_INFO part of the URL */
1304
1305  int must_close;       /* 1 if connection must be closed */
1306  int in_error_handler; /* 1 if in handler for user defined error
1307                         * pages */
1308  int internal_error;   /* 1 if an error occured while processing the
1309                         * request */
1310
1311  int buf_size;                /* Buffer size */
1312  int request_len;             /* Size of the request + headers in a buffer */
1313  int data_len;                /* Total size of data in a buffer */
1314  int status_code;             /* HTTP reply status code, e.g. 200 */
1315  int throttle;                /* Throttling, bytes/sec. <= 0 means no
1316                                * throttle */
1317  time_t last_throttle_time;   /* Last time throttled data was sent */
1318  int64_t last_throttle_bytes; /* Bytes sent this second */
1319  pthread_mutex_t mutex;       /* Used by mg_(un)lock_connection to ensure
1320                                * atomic transmissions for websockets */
1321#if defined(USE_LUA) && defined(USE_WEBSOCKET)
1322  void *lua_websocket_state; /* Lua_State for a websocket connection */
1323#endif
1324};
1325
1326
1327static pthread_key_t sTlsKey; /* Thread local storage index */
1328static int sTlsInit = 0;
1329static int thread_idx_max = 0;
1330
1331
1332struct mg_workerTLS {
1333  int is_master;
1334  unsigned long thread_idx;
1335#if defined(_WIN32) && !defined(__SYMBIAN32__)
1336  HANDLE pthread_cond_helper_mutex;
1337#endif
1338};
1339
1340/* Directory entry */
1341struct de {
1342  struct mg_connection *conn;
1343  char *file_name;
1344  struct file file;
1345};
1346
1347
1348#if defined(USE_WEBSOCKET)
1349static int is_websocket_protocol(const struct mg_connection *conn);
1350#else
1351#define is_websocket_protocol(conn) (0)
1352#endif
1353
1354
1355static int
1356mg_atomic_inc(volatile int *addr)
1357{
1358  int ret;
1359#if defined(_WIN32) && !defined(__SYMBIAN32__)
1360  /* Depending on the SDK, this function uses either
1361   * (volatile unsigned int *) or (volatile LONG *),
1362   * so whatever you use, the other SDK is likely to raise a warning. */
1363  ret = InterlockedIncrement((volatile long *)addr);
1364#elif defined(__GNUC__)                                                        \
1365    && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 0)))
1366  ret = __sync_add_and_fetch(addr, 1);
1367#else
1368  ret = (++(*addr));
1369#endif
1370  return ret;
1371}
1372
1373
1374static int
1375mg_atomic_dec(volatile int *addr)
1376{
1377  int ret;
1378#if defined(_WIN32) && !defined(__SYMBIAN32__)
1379  /* Depending on the SDK, this function uses either
1380   * (volatile unsigned int *) or (volatile LONG *),
1381   * so whatever you use, the other SDK is likely to raise a warning. */
1382  ret = InterlockedDecrement((volatile long *)addr);
1383#elif defined(__GNUC__)                                                        \
1384    && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 0)))
1385  ret = __sync_sub_and_fetch(addr, 1);
1386#else
1387  ret = (--(*addr));
1388#endif
1389  return ret;
1390}
1391
1392#if !defined(NO_THREAD_NAME)
1393#if defined(_WIN32) && defined(_MSC_VER)
1394/* Set the thread name for debugging purposes in Visual Studio
1395 * http://msdn.microsoft.com/en-us/library/xcb2z8hs.aspx
1396 */
1397#pragma pack(push, 8)
1398typedef struct tagTHREADNAME_INFO {
1399  DWORD dwType;     /* Must be 0x1000. */
1400  LPCSTR szName;    /* Pointer to name (in user addr space). */
1401  DWORD dwThreadID; /* Thread ID (-1=caller thread). */
1402  DWORD dwFlags;    /* Reserved for future use, must be zero. */
1403} THREADNAME_INFO;
1404#pragma pack(pop)
1405#elif defined(__linux__)
1406#include <sys/prctl.h>
1407#include <sys/sendfile.h>
1408#endif
1409
1410
1411static void
1412mg_set_thread_name(const char *name)
1413{
1414  char threadName[16 + 1]; /* 16 = Max. thread length in Linux/OSX/.. */
1415
1416  mg_snprintf(
1417      NULL, NULL, threadName, sizeof(threadName), "civetweb-%s", name);
1418
1419#if defined(_WIN32)
1420#if defined(_MSC_VER)
1421  /* Windows and Visual Studio Compiler */
1422  __try
1423  {
1424    THREADNAME_INFO info;
1425    info.dwType = 0x1000;
1426    info.szName = threadName;
1427    info.dwThreadID = ~0U;
1428    info.dwFlags = 0;
1429
1430    RaiseException(0x406D1388,
1431                   0,
1432                   sizeof(info) / sizeof(ULONG_PTR),
1433                   (ULONG_PTR *)&info);
1434  }
1435  __except(EXCEPTION_EXECUTE_HANDLER)
1436  {
1437  }
1438#elif defined(__MINGW32__)
1439/* No option known to set thread name for MinGW */
1440#endif
1441#elif defined(__GLIBC__)                                                       \
1442    && ((__GLIBC__ > 2) || ((__GLIBC__ == 2) && (__GLIBC_MINOR__ >= 12)))
1443  /* pthread_setname_np first appeared in glibc in version 2.12*/
1444  (void)pthread_setname_np(pthread_self(), threadName);
1445#elif defined(__linux__)
1446  /* on linux we can use the old prctl function */
1447  (void)prctl(PR_SET_NAME, threadName, 0, 0, 0);
1448#endif
1449}
1450#else /* !defined(NO_THREAD_NAME) */
1451void
1452mg_set_thread_name(const char *threadName)
1453{
1454}
1455#endif
1456
1457
1458#if defined(MG_LEGACY_INTERFACE)
1459const char **
1460mg_get_valid_option_names(void)
1461{
1462  /* This function is deprecated. Use mg_get_valid_options instead. */
1463  static const char *
1464      data[2 * sizeof(config_options) / sizeof(config_options[0])] = {0};
1465  int i;
1466
1467  for (i = 0; config_options[i].name != NULL; i++) {
1468    data[i * 2] = config_options[i].name;
1469    data[i * 2 + 1] = config_options[i].default_value;
1470  }
1471
1472  return data;
1473}
1474#endif
1475
1476
1477const struct mg_option *
1478mg_get_valid_options(void)
1479{
1480  return config_options;
1481}
1482
1483
1484static int
1485is_file_in_memory(const struct mg_connection *conn,
1486                  const char *path,
1487                  struct file *filep)
1488{
1489  size_t size = 0;
1490  if (!conn || !filep) {
1491    return 0;
1492  }
1493
1494  if (conn->ctx->callbacks.open_file) {
1495    filep->membuf = conn->ctx->callbacks.open_file(conn, path, &size);
1496    if (filep->membuf != NULL) {
1497      /* NOTE: override filep->size only on success. Otherwise, it might
1498       * break constructs like if (!mg_stat() || !mg_fopen()) ... */
1499      filep->size = size;
1500    }
1501  }
1502
1503  return filep->membuf != NULL;
1504}
1505
1506
1507static int
1508is_file_opened(const struct file *filep)
1509{
1510  if (!filep) {
1511    return 0;
1512  }
1513
1514  return filep->membuf != NULL || filep->fp != NULL;
1515}
1516
1517
1518/* mg_fopen will open a file either in memory or on the disk.
1519 * The input parameter path is a string in UTF-8 encoding.
1520 * The input parameter mode is the same as for fopen.
1521 * Either fp or membuf will be set in the output struct filep.
1522 * The function returns 1 on success, 0 on error. */
1523static int
1524mg_fopen(const struct mg_connection *conn,
1525         const char *path,
1526         const char *mode,
1527         struct file *filep)
1528{
1529  struct stat st;
1530
1531  if (!filep) {
1532    return 0;
1533  }
1534
1535  /* TODO (high): mg_fopen should only open a file, while mg_stat should
1536   * only get the file status. They should not work on different members of
1537   * the same structure (bad cohesion). */
1538  memset(filep, 0, sizeof(*filep));
1539
1540  if (stat(path, &st) == 0) {
1541    filep->size = (uint64_t)(st.st_size);
1542  }
1543
1544  if (!is_file_in_memory(conn, path, filep)) {
1545#ifdef _WIN32
1546    wchar_t wbuf[PATH_MAX], wmode[20];
1547    path_to_unicode(conn, path, wbuf, ARRAY_SIZE(wbuf));
1548    MultiByteToWideChar(CP_UTF8, 0, mode, -1, wmode, ARRAY_SIZE(wmode));
1549    filep->fp = _wfopen(wbuf, wmode);
1550#else
1551    /* Linux et al already use unicode. No need to convert. */
1552    filep->fp = fopen(path, mode);
1553#endif
1554  }
1555
1556  return is_file_opened(filep);
1557}
1558
1559
1560static void
1561mg_fclose(struct file *filep)
1562{
1563  if (filep != NULL && filep->fp != NULL) {
1564    fclose(filep->fp);
1565  }
1566}
1567
1568
1569static void
1570mg_strlcpy(register char *dst, register const char *src, size_t n)
1571{
1572  for (; *src != '\0' && n > 1; n--) {
1573    *dst++ = *src++;
1574  }
1575  *dst = '\0';
1576}
1577
1578
1579static int
1580lowercase(const char *s)
1581{
1582  return tolower(*(const unsigned char *)s);
1583}
1584
1585
1586int
1587mg_strncasecmp(const char *s1, const char *s2, size_t len)
1588{
1589  int diff = 0;
1590
1591  if (len > 0) {
1592    do {
1593      diff = lowercase(s1++) - lowercase(s2++);
1594    } while (diff == 0 && s1[-1] != '\0' && --len > 0);
1595  }
1596
1597  return diff;
1598}
1599
1600
1601int
1602mg_strcasecmp(const char *s1, const char *s2)
1603{
1604  int diff;
1605
1606  do {
1607    diff = lowercase(s1++) - lowercase(s2++);
1608  } while (diff == 0 && s1[-1] != '\0');
1609
1610  return diff;
1611}
1612
1613
1614static char *
1615mg_strndup(const char *ptr, size_t len)
1616{
1617  char *p;
1618
1619  if ((p = (char *)mg_malloc(len + 1)) != NULL) {
1620    mg_strlcpy(p, ptr, len + 1);
1621  }
1622
1623  return p;
1624}
1625
1626
1627static char *
1628mg_strdup(const char *str)
1629{
1630  return mg_strndup(str, strlen(str));
1631}
1632
1633
1634static const char *
1635mg_strcasestr(const char *big_str, const char *small_str)
1636{
1637  size_t i, big_len = strlen(big_str), small_len = strlen(small_str);
1638
1639  if (big_len >= small_len) {
1640    for (i = 0; i <= (big_len - small_len); i++) {
1641      if (mg_strncasecmp(big_str + i, small_str, small_len) == 0) {
1642        return big_str + i;
1643      }
1644    }
1645  }
1646
1647  return NULL;
1648}
1649
1650
1651/* Return null terminated string of given maximum length.
1652 * Report errors if length is exceeded. */
1653static void
1654mg_vsnprintf(const struct mg_connection *conn,
1655             int *truncated,
1656             char *buf,
1657             size_t buflen,
1658             const char *fmt,
1659             va_list ap)
1660{
1661  int n, ok;
1662
1663  if (buflen == 0) {
1664    return;
1665  }
1666
1667#ifdef __clang__
1668#pragma clang diagnostic push
1669#pragma clang diagnostic ignored "-Wformat-nonliteral"
1670/* Using fmt as a non-literal is intended here, since it is mostly called
1671 * indirectly by mg_snprintf */
1672#endif
1673
1674  n = (int)vsnprintf_impl(buf, buflen, fmt, ap);
1675  ok = (n >= 0) && ((size_t)n < buflen);
1676
1677#ifdef __clang__
1678#pragma clang diagnostic pop
1679#endif
1680
1681  if (ok) {
1682    if (truncated) {
1683      *truncated = 0;
1684    }
1685  } else {
1686    if (truncated) {
1687      *truncated = 1;
1688    }
1689    mg_cry(conn,
1690           "truncating vsnprintf buffer: [%.*s]",
1691           (int)((buflen > 200) ? 200 : (buflen - 1)),
1692           buf);
1693    n = (int)buflen - 1;
1694  }
1695  buf[n] = '\0';
1696}
1697
1698
1699static void
1700mg_snprintf(const struct mg_connection *conn,
1701            int *truncated,
1702            char *buf,
1703            size_t buflen,
1704            const char *fmt,
1705            ...)
1706{
1707  va_list ap;
1708
1709  va_start(ap, fmt);
1710  mg_vsnprintf(conn, truncated, buf, buflen, fmt, ap);
1711  va_end(ap);
1712}
1713
1714
1715static int
1716get_option_index(const char *name)
1717{
1718  int i;
1719
1720  for (i = 0; config_options[i].name != NULL; i++) {
1721    if (strcmp(config_options[i].name, name) == 0) {
1722      return i;
1723    }
1724  }
1725  return -1;
1726}
1727
1728
1729const char *
1730mg_get_option(const struct mg_context *ctx, const char *name)
1731{
1732  int i;
1733  if ((i = get_option_index(name)) == -1) {
1734    return NULL;
1735  } else if (!ctx || ctx->config[i] == NULL) {
1736    return "";
1737  } else {
1738    return ctx->config[i];
1739  }
1740}
1741
1742
1743struct mg_context *
1744mg_get_context(const struct mg_connection *conn)
1745{
1746  return (conn == NULL) ? (struct mg_context *)NULL : (conn->ctx);
1747}
1748
1749
1750void *
1751mg_get_user_data(const struct mg_context *ctx)
1752{
1753  return (ctx == NULL) ? NULL : ctx->user_data;
1754}
1755
1756
1757void
1758mg_set_user_connection_data(struct mg_connection *conn, void *data)
1759{
1760  if (conn != NULL) {
1761    conn->request_info.conn_data = data;
1762  }
1763}
1764
1765
1766void *
1767mg_get_user_connection_data(const struct mg_connection *conn)
1768{
1769  if (conn != NULL) {
1770    return conn->request_info.conn_data;
1771  }
1772  return NULL;
1773}
1774
1775
1776size_t
1777mg_get_ports(const struct mg_context *ctx, size_t size, int *ports, int *ssl)
1778{
1779  size_t i;
1780  if (!ctx) {
1781    return 0;
1782  }
1783  for (i = 0; i < size && i < ctx->num_listening_sockets; i++) {
1784    ssl[i] = ctx->listening_sockets[i].is_ssl;
1785    ports[i] = ctx->listening_ports[i];
1786  }
1787  return i;
1788}
1789
1790
1791int
1792mg_get_server_ports(const struct mg_context *ctx,
1793                    int size,
1794                    struct mg_server_ports *ports)
1795{
1796  int i, cnt = 0;
1797
1798  if (size <= 0) {
1799    return -1;
1800  }
1801  memset(ports, 0, sizeof(*ports) * (size_t)size);
1802  if (!ctx) {
1803    return -1;
1804  }
1805  if (!ctx->listening_sockets || !ctx->listening_ports) {
1806    return -1;
1807  }
1808
1809  for (i = 0; (i < size) && (i < (int)ctx->num_listening_sockets); i++) {
1810
1811    ports[cnt].port = ctx->listening_ports[i];
1812    ports[cnt].is_ssl = ctx->listening_sockets[i].is_ssl;
1813    ports[cnt].is_redirect = ctx->listening_sockets[i].ssl_redir;
1814
1815    if (ctx->listening_sockets[i].lsa.sa.sa_family == AF_INET) {
1816      /* IPv4 */
1817      ports[cnt].protocol = 1;
1818      cnt++;
1819    } else if (ctx->listening_sockets[i].lsa.sa.sa_family == AF_INET6) {
1820      /* IPv6 */
1821      ports[cnt].protocol = 3;
1822      cnt++;
1823    }
1824  }
1825
1826  return cnt;
1827}
1828
1829
1830static void
1831sockaddr_to_string(char *buf, size_t len, const union usa *usa)
1832{
1833  buf[0] = '\0';
1834
1835  if (!usa) {
1836    return;
1837  }
1838
1839  if (usa->sa.sa_family == AF_INET) {
1840    getnameinfo(&usa->sa,
1841                sizeof(usa->sin),
1842                buf,
1843                (unsigned)len,
1844                NULL,
1845                0,
1846                NI_NUMERICHOST);
1847  }
1848#if defined(USE_IPV6)
1849  else if (usa->sa.sa_family == AF_INET6) {
1850    getnameinfo(&usa->sa,
1851                sizeof(usa->sin6),
1852                buf,
1853                (unsigned)len,
1854                NULL,
1855                0,
1856                NI_NUMERICHOST);
1857  }
1858#endif
1859}
1860
1861
1862/* Convert time_t to a string. According to RFC2616, Sec 14.18, this must be
1863 * included in all responses other than 100, 101, 5xx. */
1864static void
1865gmt_time_string(char *buf, size_t buf_len, time_t *t)
1866{
1867  struct tm *tm;
1868
1869  tm = ((t != NULL) ? gmtime(t) : NULL);
1870  if (tm != NULL) {
1871    strftime(buf, buf_len, "%a, %d %b %Y %H:%M:%S GMT", tm);
1872  } else {
1873    mg_strlcpy(buf, "Thu, 01 Jan 1970 00:00:00 GMT", buf_len);
1874    buf[buf_len - 1] = '\0';
1875  }
1876}
1877
1878
1879/* difftime for struct timespec. Return value is in seconds. */
1880static double
1881mg_difftimespec(const struct timespec *ts_now, const struct timespec *ts_before)
1882{
1883  return (double)(ts_now->tv_nsec - ts_before->tv_nsec) * 1.0E-9
1884         + (double)(ts_now->tv_sec - ts_before->tv_sec);
1885}
1886
1887
1888/* Print error message to the opened error log stream. */
1889void
1890mg_cry(const struct mg_connection *conn, const char *fmt, ...)
1891{
1892  char buf[MG_BUF_LEN], src_addr[IP_ADDR_STR_LEN];
1893  va_list ap;
1894  struct file fi;
1895  time_t timestamp;
1896
1897  va_start(ap, fmt);
1898  IGNORE_UNUSED_RESULT(vsnprintf_impl(buf, sizeof(buf), fmt, ap));
1899  va_end(ap);
1900  buf[sizeof(buf) - 1] = 0;
1901
1902  if (!conn) {
1903    puts(buf);
1904    return;
1905  }
1906
1907  /* Do not lock when getting the callback value, here and below.
1908   * I suppose this is fine, since function cannot disappear in the
1909   * same way string option can. */
1910  if ((conn->ctx->callbacks.log_message == NULL)
1911      || (conn->ctx->callbacks.log_message(conn, buf) == 0)) {
1912
1913    if (conn->ctx->config[ERROR_LOG_FILE] != NULL) {
1914      if (mg_fopen(conn, conn->ctx->config[ERROR_LOG_FILE], "a+", &fi)
1915          == 0) {
1916        fi.fp = NULL;
1917      }
1918    } else {
1919      fi.fp = NULL;
1920    }
1921
1922    if (fi.fp != NULL) {
1923      flockfile(fi.fp);
1924      timestamp = time(NULL);
1925
1926      sockaddr_to_string(src_addr, sizeof(src_addr), &conn->client.rsa);
1927      fprintf(fi.fp,
1928              "[%010lu] [error] [client %s] ",
1929              (unsigned long)timestamp,
1930              src_addr);
1931
1932      if (conn->request_info.request_method != NULL) {
1933        fprintf(fi.fp,
1934                "%s %s: ",
1935                conn->request_info.request_method,
1936                conn->request_info.request_uri);
1937      }
1938
1939      fprintf(fi.fp, "%s", buf);
1940      fputc('\n', fi.fp);
1941      fflush(fi.fp);
1942      funlockfile(fi.fp);
1943      mg_fclose(&fi);
1944    }
1945  }
1946}
1947
1948
1949/* Return fake connection structure. Used for logging, if connection
1950 * is not applicable at the moment of logging. */
1951static struct mg_connection *
1952fc(struct mg_context *ctx)
1953{
1954  static struct mg_connection fake_connection;
1955  fake_connection.ctx = ctx;
1956  return &fake_connection;
1957}
1958
1959
1960const char *
1961mg_version(void)
1962{
1963  return CIVETWEB_VERSION;
1964}
1965
1966
1967const struct mg_request_info *
1968mg_get_request_info(const struct mg_connection *conn)
1969{
1970  if (!conn) {
1971    return NULL;
1972  }
1973  return &conn->request_info;
1974}
1975
1976
1977/* Skip the characters until one of the delimiters characters found.
1978 * 0-terminate resulting word. Skip the delimiter and following whitespaces.
1979 * Advance pointer to buffer to the next word. Return found 0-terminated word.
1980 * Delimiters can be quoted with quotechar. */
1981static char *
1982skip_quoted(char **buf,
1983            const char *delimiters,
1984            const char *whitespace,
1985            char quotechar)
1986{
1987  char *p, *begin_word, *end_word, *end_whitespace;
1988
1989  begin_word = *buf;
1990  end_word = begin_word + strcspn(begin_word, delimiters);
1991
1992  /* Check for quotechar */
1993  if (end_word > begin_word) {
1994    p = end_word - 1;
1995    while (*p == quotechar) {
1996      /* While the delimiter is quoted, look for the next delimiter. */
1997      /* This happens, e.g., in calls from parse_auth_header,
1998       * if the user name contains a " character. */
1999
2000      /* If there is anything beyond end_word, copy it. */
2001      if (*end_word != '\0') {
2002        size_t end_off = strcspn(end_word + 1, delimiters);
2003        memmove(p, end_word, end_off + 1);
2004        p += end_off; /* p must correspond to end_word - 1 */
2005        end_word += end_off + 1;
2006      } else {
2007        *p = '\0';
2008        break;
2009      }
2010    }
2011    for (p++; p < end_word; p++) {
2012      *p = '\0';
2013    }
2014  }
2015
2016  if (*end_word == '\0') {
2017    *buf = end_word;
2018  } else {
2019    end_whitespace = end_word + 1 + strspn(end_word + 1, whitespace);
2020
2021    for (p = end_word; p < end_whitespace; p++) {
2022      *p = '\0';
2023    }
2024
2025    *buf = end_whitespace;
2026  }
2027
2028  return begin_word;
2029}
2030
2031
2032/* Simplified version of skip_quoted without quote char
2033 * and whitespace == delimiters */
2034static char *
2035skip(char **buf, const char *delimiters)
2036{
2037  return skip_quoted(buf, delimiters, delimiters, 0);
2038}
2039
2040
2041/* Return HTTP header value, or NULL if not found. */
2042static const char *
2043get_header(const struct mg_request_info *ri, const char *name)
2044{
2045  int i;
2046  if (ri) {
2047    for (i = 0; i < ri->num_headers; i++) {
2048      if (!mg_strcasecmp(name, ri->http_headers[i].name)) {
2049        return ri->http_headers[i].value;
2050      }
2051    }
2052  }
2053
2054  return NULL;
2055}
2056
2057
2058const char *
2059mg_get_header(const struct mg_connection *conn, const char *name)
2060{
2061  if (!conn) {
2062    return NULL;
2063  }
2064
2065  return get_header(&conn->request_info, name);
2066}
2067
2068
2069/* A helper function for traversing a comma separated list of values.
2070 * It returns a list pointer shifted to the next value, or NULL if the end
2071 * of the list found.
2072 * Value is stored in val vector. If value has form "x=y", then eq_val
2073 * vector is initialized to point to the "y" part, and val vector length
2074 * is adjusted to point only to "x". */
2075static const char *
2076next_option(const char *list, struct vec *val, struct vec *eq_val)
2077{
2078  int end;
2079
2080reparse:
2081  if (val == NULL || list == NULL || *list == '\0') {
2082    /* End of the list */
2083    list = NULL;
2084  } else {
2085    /* Skip over leading LWS */
2086    while (*list == ' ' || *list == '\t')
2087      list++;
2088
2089    val->ptr = list;
2090    if ((list = strchr(val->ptr, ',')) != NULL) {
2091      /* Comma found. Store length and shift the list ptr */
2092      val->len = ((size_t)(list - val->ptr));
2093      list++;
2094    } else {
2095      /* This value is the last one */
2096      list = val->ptr + strlen(val->ptr);
2097      val->len = ((size_t)(list - val->ptr));
2098    }
2099
2100    /* Adjust length for trailing LWS */
2101    end = (int)val->len - 1;
2102    while (end >= 0 && (val->ptr[end] == ' ' || val->ptr[end] == '\t'))
2103      end--;
2104    val->len = (size_t)(end + 1);
2105
2106    if (val->len == 0) {
2107      /* Ignore any empty entries. */
2108      goto reparse;
2109    }
2110
2111    if (eq_val != NULL) {
2112      /* Value has form "x=y", adjust pointers and lengths
2113       * so that val points to "x", and eq_val points to "y". */
2114      eq_val->len = 0;
2115      eq_val->ptr = (const char *)memchr(val->ptr, '=', val->len);
2116      if (eq_val->ptr != NULL) {
2117        eq_val->ptr++; /* Skip over '=' character */
2118        eq_val->len = ((size_t)(val->ptr - eq_val->ptr)) + val->len;
2119        val->len = ((size_t)(eq_val->ptr - val->ptr)) - 1;
2120      }
2121    }
2122  }
2123
2124  return list;
2125}
2126
2127/* A helper function for checking if a comma separated list of values contains
2128 * the given option (case insensitvely).
2129 * 'header' can be NULL, in which case false is returned. */
2130static int
2131header_has_option(const char *header, const char *option)
2132{
2133  struct vec opt_vec;
2134  struct vec eq_vec;
2135
2136  assert(option != NULL);
2137  assert(option[0] != '\0');
2138
2139  while ((header = next_option(header, &opt_vec, &eq_vec)) != NULL) {
2140    if (mg_strncasecmp(option, opt_vec.ptr, opt_vec.len) == 0)
2141      return 1;
2142  }
2143
2144  return 0;
2145}
2146
2147/* Perform case-insensitive match of string against pattern */
2148static int
2149match_prefix(const char *pattern, size_t pattern_len, const char *str)
2150{
2151  const char *or_str;
2152  size_t i;
2153  int j, len, res;
2154
2155  if ((or_str = (const char *)memchr(pattern, '|', pattern_len)) != NULL) {
2156    res = match_prefix(pattern, (size_t)(or_str - pattern), str);
2157    return res > 0 ? res : match_prefix(or_str + 1,
2158                                        (size_t)((pattern + pattern_len)
2159                                                 - (or_str + 1)),
2160                                        str);
2161  }
2162
2163  for (i = 0, j = 0; i < pattern_len; i++, j++) {
2164    if (pattern[i] == '?' && str[j] != '\0') {
2165      continue;
2166    } else if (pattern[i] == '$') {
2167      return str[j] == '\0' ? j : -1;
2168    } else if (pattern[i] == '*') {
2169      i++;
2170      if (pattern[i] == '*') {
2171        i++;
2172        len = (int)strlen(str + j);
2173      } else {
2174        len = (int)strcspn(str + j, "/");
2175      }
2176      if (i == pattern_len) {
2177        return j + len;
2178      }
2179      do {
2180        res = match_prefix(pattern + i, pattern_len - i, str + j + len);
2181      } while (res == -1 && len-- > 0);
2182      return res == -1 ? -1 : j + res + len;
2183    } else if (lowercase(&pattern[i]) != lowercase(&str[j])) {
2184      return -1;
2185    }
2186  }
2187  return j;
2188}
2189
2190
2191/* HTTP 1.1 assumes keep alive if "Connection:" header is not set
2192 * This function must tolerate situations when connection info is not
2193 * set up, for example if request parsing failed. */
2194static int
2195should_keep_alive(const struct mg_connection *conn)
2196{
2197  if (conn != NULL) {
2198    const char *http_version = conn->request_info.http_version;
2199    const char *header = mg_get_header(conn, "Connection");
2200    if (conn->must_close || conn->internal_error || conn->status_code == 401
2201        || mg_strcasecmp(conn->ctx->config[ENABLE_KEEP_ALIVE], "yes") != 0
2202        || (header != NULL && !header_has_option(header, "keep-alive"))
2203        || (
 Recommendations (Experimental)  R1: (xx_conn->xx_must_close || xx_conn->xx_internal_error || xx_conn->xx_status_code == 401 || xx_mg_strcasecmp(xx_conn->xx_ctx->xx_config[ENABLE_KEEP_ALIVE], "yes") != 0 || (xx_header != NULL && !xx_header_has_option(xx_header, "keep-alive")) || (conn == NULL && must_close && internal_error))
R2: (xx_conn->xx_must_close || xx_conn->xx_internal_error || xx_conn->xx_status_code == 401 || xx_mg_strcasecmp(xx_conn->xx_ctx->xx_config[ENABLE_KEEP_ALIVE], "yes") != 0 || (xx_header != NULL && !xx_header_has_option(xx_header, "keep-alive")) || (conn == NULL && must_close && ENABLE_KEEP_ALIVE))
R3: (xx_conn->xx_must_close || xx_conn->xx_internal_error || xx_conn->xx_status_code == 401 || xx_mg_strcasecmp(xx_conn->xx_ctx->xx_config[ENABLE_KEEP_ALIVE], "yes") != 0 || (xx_header != NULL && !xx_header_has_option(xx_header, "keep-alive")) || (conn.must_close == NULL && internal_error && status_code))
R4: (xx_conn->xx_must_close || xx_conn->xx_internal_error || xx_conn->xx_status_code == 401 || xx_mg_strcasecmp(xx_conn->xx_ctx->xx_config[ENABLE_KEEP_ALIVE], "yes") != 0 || (xx_header != NULL && !xx_header_has_option(xx_header, "keep-alive")) || ((conn == NULL) && must_close && internal_error))
R5: (xx_conn->xx_must_close || xx_conn->xx_internal_error || xx_conn->xx_status_code == 401 || xx_mg_strcasecmp(xx_conn->xx_ctx->xx_config[ENABLE_KEEP_ALIVE], "yes") != 0 || (xx_header != NULL && !xx_header_has_option(xx_header, "keep-alive")) || (conn != NULL && must_close && internal_error))
 Score  Issue:  1 unfamiliar pattern(s) detected 
Cost: 76.25, Total Score: 1076.25
Class: complex_max
header
 == NULL && http_version
2204            && 0 != strcmp(http_version, "1.1"))) {
2205      return 0;
2206    }
2207    return 1;
2208  }
2209  return 0;
2210}
2211
2212
2213static int
2214should_decode_url(const struct mg_connection *conn)
2215{
2216  if (!conn || !conn->ctx) {
2217    return 0;
2218  }
2219
2220  return (mg_strcasecmp(conn->ctx->config[DECODE_URL], "yes") == 0);
2221}
2222
2223
2224static const char *
2225suggest_connection_header(const struct mg_connection *conn)
2226{
2227  return should_keep_alive(conn) ? "keep-alive" : "close";
2228}
2229
2230
2231static int
2232send_no_cache_header(struct mg_connection *conn)
2233{
2234  /* Send all current and obsolete cache opt-out directives. */
2235  return mg_printf(conn,
2236                   "Cache-Control: no-cache, no-store, "
2237                   "must-revalidate, private, max-age=0\r\n"
2238                   "Pragma: no-cache\r\n"
2239                   "Expires: 0\r\n");
2240}
2241
2242
2243static int
2244send_static_cache_header(struct mg_connection *conn)
2245{
2246#if !defined(NO_CACHING)
2247  /* Read the server config to check how long a file may be cached.
2248   * The configuration is in seconds. */
2249  int max_age = atoi(conn->ctx->config[STATIC_FILE_MAX_AGE]);
2250  if (max_age <= 0) {
2251    /* 0 means "do not cache". All values <0 are reserved
2252     * and may be used differently in the future. */
2253    /* If a file should not be cached, do not only send
2254     * max-age=0, but also pragmas and Expires headers. */
2255    return send_no_cache_header(conn);
2256  }
2257
2258  /* Use "Cache-Control: max-age" instead of "Expires" header.
2259   * Reason: see https://www.mnot.net/blog/2007/05/15/expires_max-age */
2260  /* See also https://www.mnot.net/cache_docs/ */
2261  /* According to RFC 2616, Section 14.21, caching times should not exceed
2262   * one year. A year with 365 days corresponds to 31536000 seconds, a leap
2263   * year to 31622400 seconds. For the moment, we just send whatever has
2264   * been configured, still the behavior for >1 year should be considered
2265   * as undefined. */
2266  return mg_printf(conn, "Cache-Control: max-age=%u\r\n", (unsigned)max_age);
2267#else  /* NO_CACHING */
2268  return send_no_cache_header(conn);
2269#endif /* !NO_CACHING */
2270}
2271
2272
2273static void handle_file_based_request(struct mg_connection *conn,
2274                                      const char *path,
2275                                      struct file *filep);
2276
2277static int
2278mg_stat(struct mg_connection *conn, const char *path, struct file *filep);
2279
2280
2281const char *
2282mg_get_response_code_text(struct mg_connection *conn, int response_code)
2283{
2284  /* See IANA HTTP status code assignment:
2285   * http://www.iana.org/assignments/http-status-codes/http-status-codes.xhtml
2286   */
2287
2288  switch (response_code) {
2289  /* RFC2616 Section 10.1 - Informational 1xx */
2290  case 100:
2291    return "Continue"; /* RFC2616 Section 10.1.1 */
2292  case 101:
2293    return "Switching Protocols"; /* RFC2616 Section 10.1.2 */
2294  case 102:
2295    return "Processing"; /* RFC2518 Section 10.1 */
2296
2297  /* RFC2616 Section 10.2 - Successful 2xx */
2298  case 200:
2299    return "OK"; /* RFC2616 Section 10.2.1 */
2300  case 201:
2301    return "Created"; /* RFC2616 Section 10.2.2 */
2302  case 202:
2303    return "Accepted"; /* RFC2616 Section 10.2.3 */
2304  case 203:
2305    return "Non-Authoritative Information"; /* RFC2616 Section 10.2.4 */
2306  case 204:
2307    return "No Content"; /* RFC2616 Section 10.2.5 */
2308  case 205:
2309    return "Reset Content"; /* RFC2616 Section 10.2.6 */
2310  case 206:
2311    return "Partial Content"; /* RFC2616 Section 10.2.7 */
2312  case 207:
2313    return "Multi-Status"; /* RFC2518 Section 10.2, RFC4918 Section 11.1 */
2314  case 208:
2315    return "Already Reported"; /* RFC5842 Section 7.1 */
2316
2317  case 226:
2318    return "IM used"; /* RFC3229 Section 10.4.1 */
2319
2320  /* RFC2616 Section 10.3 - Redirection 3xx */
2321  case 300:
2322    return "Multiple Choices"; /* RFC2616 Section 10.3.1 */
2323  case 301:
2324    return "Moved Permanently"; /* RFC2616 Section 10.3.2 */
2325  case 302:
2326    return "Found"; /* RFC2616 Section 10.3.3 */
2327  case 303:
2328    return "See Other"; /* RFC2616 Section 10.3.4 */
2329  case 304:
2330    return "Not Modified"; /* RFC2616 Section 10.3.5 */
2331  case 305:
2332    return "Use Proxy"; /* RFC2616 Section 10.3.6 */
2333  case 307:
2334    return "Temporary Redirect"; /* RFC2616 Section 10.3.8 */
2335  case 308:
2336    return "Permanent Redirect"; /* RFC7238 Section 3 */
2337
2338  /* RFC2616 Section 10.4 - Client Error 4xx */
2339  case 400:
2340    return "Bad Request"; /* RFC2616 Section 10.4.1 */
2341  case 401:
2342    return "Unauthorized"; /* RFC2616 Section 10.4.2 */
2343  case 402:
2344    return "Payment Required"; /* RFC2616 Section 10.4.3 */
2345  case 403:
2346    return "Forbidden"; /* RFC2616 Section 10.4.4 */
2347  case 404:
2348    return "Not Found"; /* RFC2616 Section 10.4.5 */
2349  case 405:
2350    return "Method Not Allowed"; /* RFC2616 Section 10.4.6 */
2351  case 406:
2352    return "Not Acceptable"; /* RFC2616 Section 10.4.7 */
2353  case 407:
2354    return "Proxy Authentication Required"; /* RFC2616 Section 10.4.8 */
2355  case 408:
2356    return "Request Time-out"; /* RFC2616 Section 10.4.9 */
2357  case 409:
2358    return "Conflict"; /* RFC2616 Section 10.4.10 */
2359  case 410:
2360    return "Gone"; /* RFC2616 Section 10.4.11 */
2361  case 411:
2362    return "Length Required"; /* RFC2616 Section 10.4.12 */
2363  case 412:
2364    return "Precondition Failed"; /* RFC2616 Section 10.4.13 */
2365  case 413:
2366    return "Request Entity Too Large"; /* RFC2616 Section 10.4.14 */
2367  case 414:
2368    return "Request-URI Too Large"; /* RFC2616 Section 10.4.15 */
2369  case 415:
2370    return "Unsupported Media Type"; /* RFC2616 Section 10.4.16 */
2371  case 416:
2372    return "Requested range not satisfiable"; /* RFC2616 Section 10.4.17 */
2373  case 417:
2374    return "Expectation Failed"; /* RFC2616 Section 10.4.18 */
2375
2376  case 421:
2377    return "Misdirected Request"; /* RFC7540 Section 9.1.2 */
2378  case 422:
2379    return "Unproccessable entity"; /* RFC2518 Section 10.3, RFC4918
2380                                     * Section 11.2 */
2381  case 423:
2382    return "Locked"; /* RFC2518 Section 10.4, RFC4918 Section 11.3 */
2383  case 424:
2384    return "Failed Dependency"; /* RFC2518 Section 10.5, RFC4918
2385                                 * Section 11.4 */
2386
2387  case 426:
2388    return "Upgrade Required"; /* RFC 2817 Section 4 */
2389
2390  case 428:
2391    return "Precondition Required"; /* RFC 6585, Section 3 */
2392  case 429:
2393    return "Too Many Requests"; /* RFC 6585, Section 4 */
2394
2395  case 431:
2396    return "Request Header Fields Too Large"; /* RFC 6585, Section 5 */
2397
2398  case 451:
2399    return "Unavailable For Legal Reasons"; /* draft-tbray-http-legally-restricted-status-05,
2400                                             * Section 3 */
2401
2402  /* RFC2616 Section 10.5 - Server Error 5xx */
2403  case 500:
2404    return "Internal Server Error"; /* RFC2616 Section 10.5.1 */
2405  case 501:
2406    return "Not Implemented"; /* RFC2616 Section 10.5.2 */
2407  case 502:
2408    return "Bad Gateway"; /* RFC2616 Section 10.5.3 */
2409  case 503:
2410    return "Service Unavailable"; /* RFC2616 Section 10.5.4 */
2411  case 504:
2412    return "Gateway Time-out"; /* RFC2616 Section 10.5.5 */
2413  case 505:
2414    return "HTTP Version not supported"; /* RFC2616 Section 10.5.6 */
2415  case 506:
2416    return "Variant Also Negotiates"; /* RFC 2295, Section 8.1 */
2417  case 507:
2418    return "Insufficient Storage"; /* RFC2518 Section 10.6, RFC4918
2419                                    * Section 11.5 */
2420  case 508:
2421    return "Loop Detected"; /* RFC5842 Section 7.1 */
2422
2423  case 510:
2424    return "Not Extended"; /* RFC 2774, Section 7 */
2425  case 511:
2426    return "Network Authentication Required"; /* RFC 6585, Section 6 */
2427
2428  /* Other status codes, not shown in the IANA HTTP status code assignment.
2429   * E.g., "de facto" standards due to common use, ... */
2430  case 418:
2431    return "I am a teapot"; /* RFC2324 Section 2.3.2 */
2432  case 419:
2433    return "Authentication Timeout"; /* common use */
2434  case 420:
2435    return "Enhance Your Calm"; /* common use */
2436  case 440:
2437    return "Login Timeout"; /* common use */
2438  case 509:
2439    return "Bandwidth Limit Exceeded"; /* common use */
2440
2441  default:
2442    /* This error code is unknown. This should not happen. */
2443    if (conn) {
2444      mg_cry(conn, "Unknown HTTP response code: %u", response_code);
2445    }
2446
2447    /* Return at least a category according to RFC 2616 Section 10. */
2448    if (response_code >= 100 && response_code < 200) {
2449      /* Unknown informational status code */
2450      return "Information";
2451    }
2452    if (response_code >= 200 && response_code < 300) {
2453      /* Unknown success code */
2454      return "Success";
2455    }
2456    if (response_code >= 300 && response_code < 400) {
2457      /* Unknown redirection code */
2458      return "Redirection";
2459    }
2460    if (response_code >= 400 && response_code < 500) {
2461      /* Unknown request error code */
2462      return "Client Error";
2463    }
2464    if (response_code >= 500 && response_code < 600) {
2465      /* Unknown server error code */
2466      return "Server Error";
2467    }
2468
2469    /* Response code not even within reasonable range */
2470    return "";
2471  }
2472}
2473
2474
2475static void send_http_error(struct mg_connection *,
2476                            int,
2477                            PRINTF_FORMAT_STRING(const char *fmt),
2478                            ...) PRINTF_ARGS(3, 4);
2479
2480static void
2481send_http_error(struct mg_connection *conn, int status, const char *fmt, ...)
2482{
2483  char buf[MG_BUF_LEN];
2484  va_list ap;
2485  int len, i, page_handler_found, scope, truncated;
2486  char date[64];
2487  time_t curtime = time(NULL);
2488  const char *error_handler = NULL;
2489  struct file error_page_file = STRUCT_FILE_INITIALIZER;
2490  const char *error_page_file_ext, *tstr;
2491
2492  const char *status_text = mg_get_response_code_text(conn, status);
2493
2494  if (conn == NULL) {
2495    return;
2496  }
2497
2498  conn->status_code = status;
2499  if (
 Recommendations (Experimental)  R1: (conn || in_error_handler == NULL || ctx)
R2: (conn || in_error_handler == NULL || in_error_handler->ctx(callbacks))
R3: (conn->in_error_handler->ctx || conn->callbacks->http_error == NULL || status(conn))
R4: (conn || (in_error_handler->ctx == NULL) || callbacks(in_error_handler->ctx))
R5: (conn || in_error_handler == NULL || ctx(callbacks))
 Score  Issue:  1 unfamiliar pattern(s) detected 
Cost: 22.00, Total Score: 1022.00
Class: complex_2
conn
->in_error_handler || conn->ctx->callbacks.http_error == NULL
2500      || conn->ctx->callbacks.http_error(conn, status)) {
2501    if (!conn->in_error_handler) {
2502      /* Send user defined error pages, if defined */
2503      error_handler = conn->ctx->config[ERROR_PAGES];
2504      error_page_file_ext = conn->ctx->config[INDEX_FILES];
2505      page_handler_found = 0;
2506      if (error_handler != NULL) {
2507        for (scope = 1; (scope <= 3) && !page_handler_found; scope++) {
2508          switch (scope) {
2509          case 1: /* Handler for specific error, e.g. 404 error */
2510            mg_snprintf(conn,
2511                        &truncated,
2512                        buf,
2513                        sizeof(buf) - 32,
2514                        "%serror%03u.",
2515                        error_handler,
2516                        status);
2517            break;
2518          case 2: /* Handler for error group, e.g., 5xx error handler
2519                   * for all server errors (500-599) */
2520            mg_snprintf(conn,
2521                        &truncated,
2522                        buf,
2523                        sizeof(buf) - 32,
2524                        "%serror%01uxx.",
2525                        error_handler,
2526                        status / 100);
2527            break;
2528          default: /* Handler for all errors */
2529            mg_snprintf(conn,
2530                        &truncated,
2531                        buf,
2532                        sizeof(buf) - 32,
2533                        "%serror.",
2534                        error_handler);
2535            break;
2536          }
2537
2538          /* String truncation in buf may only occur if error_handler
2539           * is too long. This string is from the config, not from a
2540           * client. */
2541          (void)truncated;
2542
2543          len = (int)strlen(buf);
2544
2545          tstr = strchr(error_page_file_ext, '.');
2546
2547          while (tstr) {
2548            for (i = 1; i < 32 && tstr[i] != 0 && tstr[i] != ',';
2549                 i++)
2550              buf[len + i - 1] = tstr[i];
2551            buf[len + i - 1] = 0;
2552            if (mg_stat(conn, buf, &error_page_file)) {
2553              page_handler_found = 1;
2554              break;
2555            }
2556            tstr = strchr(tstr + i, '.');
2557          }
2558        }
2559      }
2560
2561      if (page_handler_found) {
2562        conn->in_error_handler = 1;
2563        handle_file_based_request(conn, buf, &error_page_file);
2564        conn->in_error_handler = 0;
2565        return;
2566      }
2567    }
2568
2569    /* No custom error page. Send default error page. */
2570    gmt_time_string(date, sizeof(date), &curtime);
2571
2572    conn->must_close = 1;
2573    mg_printf(conn, "HTTP/1.1 %d %s\r\n", status, status_text);
2574    send_no_cache_header(conn);
2575    mg_printf(conn,
2576              "Date: %s\r\n"
2577              "Connection: close\r\n\r\n",
2578              date);
2579
2580    /* Errors 1xx, 204 and 304 MUST NOT send a body */
2581    if (status > 199 && status != 204 && status != 304) {
2582
2583      mg_printf(conn, "Error %d: %s\n", status, status_text);
2584
2585      if (fmt != NULL) {
2586        va_start(ap, fmt);
2587        mg_vsnprintf(conn, NULL, buf, sizeof(buf), fmt, ap);
2588        va_end(ap);
2589        mg_write(conn, buf, strlen(buf));
2590        DEBUG_TRACE("Error %i - [%s]", status, buf);
2591      }
2592
2593    } else {
2594      /* No body allowed. Close the connection. */
2595      DEBUG_TRACE("Error %i", status);
2596    }
2597  }
2598}
2599
2600#if defined(_WIN32) && !defined(__SYMBIAN32__)
2601/* Create substitutes for POSIX functions in Win32. */
2602
2603#if defined(__MINGW32__)
2604/* Show no warning in case system functions are not used. */
2605#pragma GCC diagnostic push
2606#pragma GCC diagnostic ignored "-Wunused-function"
2607#endif
2608
2609
2610static int
2611pthread_mutex_init(pthread_mutex_t *mutex, void *unused)
2612{
2613  (void)unused;
2614  *mutex = CreateMutex(NULL, FALSE, NULL);
2615  return *mutex == NULL ? -1 : 0;
2616}
2617
2618
2619static int
2620pthread_mutex_destroy(pthread_mutex_t *mutex)
2621{
2622  return CloseHandle(*mutex) == 0 ? -1 : 0;
2623}
2624
2625
2626static int
2627pthread_mutex_lock(pthread_mutex_t *mutex)
2628{
2629  return WaitForSingleObject(*mutex, INFINITE) == WAIT_OBJECT_0 ? 0 : -1;
2630}
2631
2632
2633#ifdef ENABLE_UNUSED_PTHREAD_FUNCTIONS
2634static int
2635pthread_mutex_trylock(pthread_mutex_t *mutex)
2636{
2637  switch (WaitForSingleObject(*mutex, 0)) {
2638  case WAIT_OBJECT_0:
2639    return 0;
2640  case WAIT_TIMEOUT:
2641    return -2; /* EBUSY */
2642  }
2643  return -1;
2644}
2645#endif
2646
2647
2648static int
2649pthread_mutex_unlock(pthread_mutex_t *mutex)
2650{
2651  return ReleaseMutex(*mutex) == 0 ? -1 : 0;
2652}
2653
2654
2655#ifndef WIN_PTHREADS_TIME_H
2656static int
2657clock_gettime(clockid_t clk_id, struct timespec *tp)
2658{
2659  FILETIME ft;
2660  ULARGE_INTEGER li;
2661  BOOL ok = FALSE;
2662  double d;
2663  static double perfcnt_per_sec = 0.0;
2664
2665  if (tp) {
2666    memset(tp, 0, sizeof(*tp));
2667    if (clk_id == CLOCK_REALTIME) {
2668      GetSystemTimeAsFileTime(&ft);
2669      li.LowPart = ft.dwLowDateTime;
2670      li.HighPart = ft.dwHighDateTime;
2671      li.QuadPart -= 116444736000000000; /* 1.1.1970 in filedate */
2672      tp->tv_sec = (time_t)(li.QuadPart / 10000000);
2673      tp->tv_nsec = (long)(li.QuadPart % 10000000) * 100;
2674      ok = TRUE;
2675    } else if (clk_id == CLOCK_MONOTONIC) {
2676      if (perfcnt_per_sec == 0.0) {
2677        QueryPerformanceFrequency((LARGE_INTEGER *)&li);
2678        perfcnt_per_sec = 1.0 / li.QuadPart;
2679      }
2680      if (perfcnt_per_sec != 0.0) {
2681        QueryPerformanceCounter((LARGE_INTEGER *)&li);
2682        d = li.QuadPart * perfcnt_per_sec;
2683        tp->tv_sec = (time_t)d;
2684        d -= tp->tv_sec;
2685        tp->tv_nsec = (long)(d * 1.0E9);
2686        ok = TRUE;
2687      }
2688    }
2689  }
2690
2691  return ok ? 0 : -1;
2692}
2693#endif
2694
2695
2696static int
2697pthread_cond_init(pthread_cond_t *cv, const void *unused)
2698{
2699  (void)unused;
2700  InitializeCriticalSection(&cv->threadIdSec);
2701  cv->waitingthreadcount = 0;
2702  cv->waitingthreadhdls =
2703      (pthread_t *)mg_calloc(MAX_WORKER_THREADS, sizeof(pthread_t));
2704  return (cv->waitingthreadhdls != NULL) ? 0 : -1;
2705}
2706
2707
2708static int
2709pthread_cond_timedwait(pthread_cond_t *cv,
2710                       pthread_mutex_t *mutex,
2711                       const struct timespec *abstime)
2712{
2713  struct mg_workerTLS *tls =
2714      (struct mg_workerTLS *)pthread_getspecific(sTlsKey);
2715  int ok;
2716  struct timespec tsnow;
2717  int64_t nsnow, nswaitabs, nswaitrel;
2718  DWORD mswaitrel;
2719
2720  EnterCriticalSection(&cv->threadIdSec);
2721  assert(cv->waitingthreadcount < MAX_WORKER_THREADS);
2722  cv->waitingthreadhdls[cv->waitingthreadcount] =
2723      tls->pthread_cond_helper_mutex;
2724  cv->waitingthreadcount++;
2725  LeaveCriticalSection(&cv->threadIdSec);
2726
2727  if (abstime) {
2728    clock_gettime(CLOCK_REALTIME, &tsnow);
2729    nsnow = (((int64_t)tsnow.tv_sec) * 1000000000) + tsnow.tv_nsec;
2730    nswaitabs =
2731        (((int64_t)abstime->tv_sec) * 1000000000) + abstime->tv_nsec;
2732    nswaitrel = nswaitabs - nsnow;
2733    if (nswaitrel < 0) {
2734      nswaitrel = 0;
2735    }
2736    mswaitrel = (DWORD)(nswaitrel / 1000000);
2737  } else {
2738    mswaitrel = INFINITE;
2739  }
2740
2741  pthread_mutex_unlock(mutex);
2742  ok = (WAIT_OBJECT_0
2743        == WaitForSingleObject(tls->pthread_cond_helper_mutex, mswaitrel));
2744  pthread_mutex_lock(mutex);
2745
2746  return ok ? 0 : -1;
2747}
2748
2749
2750static int
2751pthread_cond_wait(pthread_cond_t *cv, pthread_mutex_t *mutex)
2752{
2753  return pthread_cond_timedwait(cv, mutex, NULL);
2754}
2755
2756
2757static int
2758pthread_cond_signal(pthread_cond_t *cv)
2759{
2760  int i;
2761  HANDLE wkup = NULL;
2762  BOOL ok = FALSE;
2763
2764  EnterCriticalSection(&cv->threadIdSec);
2765  if (cv->waitingthreadcount) {
2766    wkup = cv->waitingthreadhdls[0];
2767    ok = SetEvent(wkup);
2768
2769    for (i = 1; i < cv->waitingthreadcount; i++) {
2770      cv->waitingthreadhdls[i - 1] = cv->waitingthreadhdls[i];
2771    }
2772    cv->waitingthreadcount--;
2773
2774    assert(ok);
2775  }
2776  LeaveCriticalSection(&cv->threadIdSec);
2777
2778  return ok ? 0 : 1;
2779}
2780
2781
2782static int
2783pthread_cond_broadcast(pthread_cond_t *cv)
2784{
2785  EnterCriticalSection(&cv->threadIdSec);
2786  while (cv->waitingthreadcount) {
2787    pthread_cond_signal(cv);
2788  }
2789  LeaveCriticalSection(&cv->threadIdSec);
2790
2791  return 0;
2792}
2793
2794
2795static int
2796pthread_cond_destroy(pthread_cond_t *cv)
2797{
2798  EnterCriticalSection(&cv->threadIdSec);
2799  assert(cv->waitingthreadcount == 0);
2800  mg_free(cv->waitingthreadhdls);
2801  cv->waitingthreadhdls = 0;
2802  LeaveCriticalSection(&cv->threadIdSec);
2803  DeleteCriticalSection(&cv->threadIdSec);
2804
2805  return 0;
2806}
2807
2808
2809#if defined(__MINGW32__)
2810/* Enable unused function warning again */
2811#pragma GCC diagnostic pop
2812#endif
2813
2814
2815/* For Windows, change all slashes to backslashes in path names. */
2816static void
2817change_slashes_to_backslashes(char *path)
2818{
2819  int i;
2820
2821  for (i = 0; path[i] != '\0'; i++) {
2822    if (path[i] == '/') {
2823      path[i] = '\\';
2824    }
2825
2826    /* remove double backslash (check i > 0 to preserve UNC paths,
2827     * like \\server\file.txt) */
2828    if ((path[i] == '\\') && (i > 0)) {
2829      while (path[i + 1] == '\\' || path[i + 1] == '/') {
2830        (void)memmove(path + i + 1, path + i + 2, strlen(path + i + 1));
2831      }
2832    }
2833  }
2834}
2835
2836
2837static int
2838mg_wcscasecmp(const wchar_t *s1, const wchar_t *s2)
2839{
2840  int diff;
2841
2842  do {
2843    diff = tolower(*s1) - tolower(*s2);
2844    s1++;
2845    s2++;
2846  } while (diff == 0 && s1[-1] != '\0');
2847
2848  return diff;
2849}
2850
2851
2852/* Encode 'path' which is assumed UTF-8 string, into UNICODE string.
2853 * wbuf and wbuf_len is a target buffer and its length. */
2854static void
2855path_to_unicode(const struct mg_connection *conn,
2856                const char *path,
2857                wchar_t *wbuf,
2858                size_t wbuf_len)
2859{
2860  char buf[PATH_MAX], buf2[PATH_MAX];
2861  wchar_t wbuf2[MAX_PATH + 1];
2862  DWORD long_len, err;
2863  int (*fcompare)(const wchar_t *, const wchar_t *) = mg_wcscasecmp;
2864
2865  mg_strlcpy(buf, path, sizeof(buf));
2866  change_slashes_to_backslashes(buf);
2867
2868  /* Convert to Unicode and back. If doubly-converted string does not
2869   * match the original, something is fishy, reject. */
2870  memset(wbuf, 0, wbuf_len * sizeof(wchar_t));
2871  MultiByteToWideChar(CP_UTF8, 0, buf, -1, wbuf, (int)wbuf_len);
2872  WideCharToMultiByte(
2873      CP_UTF8, 0, wbuf, (int)wbuf_len, buf2, sizeof(buf2), NULL, NULL);
2874  if (strcmp(buf, buf2) != 0) {
2875    wbuf[0] = L'\0';
2876  }
2877
2878  /* TODO: Add a configuration to switch between case sensitive and
2879   * case insensitive URIs for Windows server. */
2880  /*
2881  if (conn) {
2882      if (conn->ctx->config[WINDOWS_CASE_SENSITIVE]) {
2883          fcompare = wcscmp;
2884      }
2885  }
2886  */
2887  (void)conn; /* conn is currently unused */
2888
2889  /* Only accept a full file path, not a Windows short (8.3) path. */
2890  memset(wbuf2, 0, ARRAY_SIZE(wbuf2) * sizeof(wchar_t));
2891  long_len = GetLongPathNameW(wbuf, wbuf2, ARRAY_SIZE(wbuf2) - 1);
2892  if (long_len == 0) {
2893    err = GetLastError();
2894    if (err == ERROR_FILE_NOT_FOUND) {
2895      /* File does not exist. This is not always a problem here. */
2896      return;
2897    }
2898  }
2899  if (
 Recommendations (Experimental)  R1: ((long_len != ARRAY_SIZE(wbuf2)) || (fcompare(wbuf2) != 0))
R2: ((long_len != ARRAY_SIZE(wbuf2)) || (fcompare(wbuf2, wbuf, long_len) != 0))
R3: ((long_len >= ARRAY_SIZE()) || (wbuf2(long_len) == 0))
R4: ((long_len > ARRAY_SIZE(wbuf2, fcompare)) && (ARRAY_SIZE(wbuf2fcompare) != 0))
R5: ((long_len == ARRAY_SIZE(0)) || (wbuf2(long_len) == 0))
 Score  Issue:  1 unfamiliar pattern(s) detected 
Cost: 7.25, Total Score: 1007.25
Class: complex_2
(
long_len >= ARRAY_SIZE(wbuf2)) || (fcompare(wbuf, wbuf2) != 0)) {
2900    /* Short name is used. */
2901    wbuf[0] = L'\0';
2902  }
2903}
2904
2905
2906#if defined(_WIN32_WCE)
2907/* Create substitutes for POSIX functions in Win32. */
2908
2909#if defined(__MINGW32__)
2910/* Show no warning in case system functions are not used. */
2911#pragma GCC diagnostic push
2912#pragma GCC diagnostic ignored "-Wunused-function"
2913#endif
2914
2915
2916static time_t
2917time(time_t *ptime)
2918{
2919  time_t t;
2920  SYSTEMTIME st;
2921  FILETIME ft;
2922
2923  GetSystemTime(&st);
2924  SystemTimeToFileTime(&st, &ft);
2925  t = SYS2UNIX_TIME(ft.dwLowDateTime, ft.dwHighDateTime);
2926
2927  if (ptime != NULL) {
2928    *ptime = t;
2929  }
2930
2931  return t;
2932}
2933
2934
2935static struct tm *
2936localtime(const time_t *ptime, struct tm *ptm)
2937{
2938  int64_t t = ((int64_t)*ptime) * RATE_DIFF + EPOCH_DIFF;
2939  FILETIME ft, lft;
2940  SYSTEMTIME st;
2941  TIME_ZONE_INFORMATION tzinfo;
2942
2943  if (ptm == NULL) {
2944    return NULL;
2945  }
2946
2947  *(int64_t *)&ft = t;
2948  FileTimeToLocalFileTime(&ft, &lft);
2949  FileTimeToSystemTime(&lft, &st);
2950  ptm->tm_year = st.wYear - 1900;
2951  ptm->tm_mon = st.wMonth - 1;
2952  ptm->tm_wday = st.wDayOfWeek;
2953  ptm->tm_mday = st.wDay;
2954  ptm->tm_hour = st.wHour;
2955  ptm->tm_min = st.wMinute;
2956  ptm->tm_sec = st.wSecond;
2957  ptm->tm_yday = 0; /* hope nobody uses this */
2958  ptm->tm_isdst =
2959      GetTimeZoneInformation(&tzinfo) == TIME_ZONE_ID_DAYLIGHT ? 1 : 0;
2960
2961  return ptm;
2962}
2963
2964
2965static struct tm *
2966gmtime(const time_t *ptime, struct tm *ptm)
2967{
2968  /* FIXME(lsm): fix this. */
2969  return localtime(ptime, ptm);
2970}
2971
2972
2973static size_t
2974strftime(char *dst, size_t dst_size, const char *fmt, const struct tm *tm)
2975{
2976  (void)mg_snprintf(NULL, dst, dst_size, "implement strftime() for WinCE");
2977  return 0;
2978}
2979
2980
2981#if defined(__MINGW32__)
2982/* Enable unused function warning again */
2983#pragma GCC diagnostic pop
2984#endif
2985
2986#endif
2987
2988
2989/* Windows happily opens files with some garbage at the end of file name.
2990 * For example, fopen("a.cgi    ", "r") on Windows successfully opens
2991 * "a.cgi", despite one would expect an error back.
2992 * This function returns non-0 if path ends with some garbage. */
2993static int
2994path_cannot_disclose_cgi(const char *path)
2995{
2996  static const char *allowed_last_characters = "_-";
2997  int last = path[strlen(path) - 1];
2998  return isalnum(last) || strchr(allowed_last_characters, last) != NULL;
2999}
3000
3001
3002static int
3003mg_stat(struct mg_connection *conn, const char *path, struct file *filep)
3004{
3005  wchar_t wbuf[PATH_MAX];
3006  WIN32_FILE_ATTRIBUTE_DATA info;
3007  time_t creation_time;
3008
3009  if (!filep) {
3010    return 0;
3011  }
3012  memset(filep, 0, sizeof(*filep));
3013
3014  if (conn && is_file_in_memory(conn, path, filep)) {
3015    /* filep->is_directory = 0; filep->gzipped = 0; .. already done by
3016     * memset */
3017    filep->last_modified = time(NULL);
3018    /* last_modified = now ... assumes the file may change during runtime,
3019     * so every mg_fopen call may return different data */
3020    /* last_modified = conn->ctx.start_time;
3021     * May be used it the data does not change during runtime. This allows
3022     * browser caching. Since we do not know, we have to assume the file
3023     * in memory may change. */
3024    return 1;
3025  }
3026
3027    if (path && path[4] == 0 && memcmp(path, "www/", 4) == 0)
3028    {
3029        filep->size = 512;
3030        filep->is_directory = 1;
3031        return 1;
3032    }
3033
3034  path_to_unicode(conn, path, wbuf, ARRAY_SIZE(wbuf));
3035  if (GetFileAttributesExW(wbuf, GetFileExInfoStandard, &info) != 0) {
3036    filep->size = MAKEUQUAD(info.nFileSizeLow, info.nFileSizeHigh);
3037    filep->last_modified =
3038        SYS2UNIX_TIME(info.ftLastWriteTime.dwLowDateTime,
3039                      info.ftLastWriteTime.dwHighDateTime);
3040
3041    /* On Windows, the file creation time can be higher than the
3042     * modification time, e.g. when a file is copied.
3043     * Since the Last-Modified timestamp is used for caching
3044     * it should be based on the most recent timestamp. */
3045    creation_time = SYS2UNIX_TIME(info.ftCreationTime.dwLowDateTime,
3046                                  info.ftCreationTime.dwHighDateTime);
3047    if (creation_time > filep->last_modified) {
3048      filep->last_modified = creation_time;
3049    }
3050
3051    filep->is_directory = info.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;
3052    /* If file name is fishy, reset the file structure and return
3053     * error.
3054     * Note it is important to reset, not just return the error, cause
3055     * functions like is_file_opened() check the struct. */
3056    if (!filep->is_directory && !path_cannot_disclose_cgi(path)) {
3057      memset(filep, 0, sizeof(*filep));
3058      return 0;
3059    }
3060
3061    return 1;
3062  }
3063
3064  return 0;
3065}
3066
3067
3068static int
3069mg_remove(const struct mg_connection *conn, const char *path)
3070{
3071  wchar_t wbuf[PATH_MAX];
3072  path_to_unicode(conn, path, wbuf, ARRAY_SIZE(wbuf));
3073  return DeleteFileW(wbuf) ? 0 : -1;
3074}
3075
3076
3077static int
3078mg_mkdir(const struct mg_connection *conn, const char *path, int mode)
3079{
3080  wchar_t wbuf[PATH_MAX];
3081  (void)mode;
3082  path_to_unicode(conn, path, wbuf, ARRAY_SIZE(wbuf));
3083  return CreateDirectoryW(wbuf, NULL) ? 0 : -1;
3084}
3085
3086
3087/* Create substitutes for POSIX functions in Win32. */
3088
3089#if defined(__MINGW32__)
3090/* Show no warning in case system functions are not used. */
3091#pragma GCC diagnostic push
3092#pragma GCC diagnostic ignored "-Wunused-function"
3093#endif
3094
3095
3096/* Implementation of POSIX opendir/closedir/readdir for Windows. */
3097static DIR *
3098mg_opendir(const struct mg_connection *conn, const char *name)
3099{
3100  DIR *dir = NULL;
3101  wchar_t wpath[PATH_MAX];
3102  DWORD attrs;
3103
3104  if (name == NULL) {
3105    SetLastError(ERROR_BAD_ARGUMENTS);
3106  } else if ((dir = (DIR *)mg_malloc(sizeof(*dir))) == NULL) {
3107    SetLastError(ERROR_NOT_ENOUGH_MEMORY);
3108  } else {
3109    path_to_unicode(conn, name, wpath, ARRAY_SIZE(wpath));
3110    attrs = GetFileAttributesW(wpath);
3111    if (attrs != 0xFFFFFFFF && ((attrs & FILE_ATTRIBUTE_DIRECTORY)
3112                                == FILE_ATTRIBUTE_DIRECTORY)) {
3113      (void)wcscat(wpath, L"\\*");
3114      dir->handle = FindFirstFileW(wpath, &dir->info);
3115      dir->result.d_name[0] = '\0';
3116    } else {
3117      mg_free(dir);
3118      dir = NULL;
3119    }
3120  }
3121
3122  return dir;
3123}
3124
3125
3126static int
3127mg_closedir(DIR *dir)
3128{
3129  int result = 0;
3130
3131  if (dir != NULL) {
3132    if (dir->handle != INVALID_HANDLE_VALUE)
3133      result = FindClose(dir->handle) ? 0 : -1;
3134
3135    mg_free(dir);
3136  } else {
3137    result = -1;
3138    SetLastError(ERROR_BAD_ARGUMENTS);
3139  }
3140
3141  return result;
3142}
3143
3144
3145static struct dirent *
3146mg_readdir(DIR *dir)
3147{
3148  struct dirent *result = 0;
3149
3150  if (dir) {
3151    if (dir->handle != INVALID_HANDLE_VALUE) {
3152      result = &dir->result;
3153      (void)WideCharToMultiByte(CP_UTF8,
3154                                0,
3155                                dir->info.cFileName,
3156                                -1,
3157                                result->d_name,
3158                                sizeof(result->d_name),
3159                                NULL,
3160                                NULL);
3161
3162      if (!FindNextFileW(dir->handle, &dir->info)) {
3163        (void)FindClose(dir->handle);
3164        dir->handle = INVALID_HANDLE_VALUE;
3165      }
3166
3167    } else {
3168      SetLastError(ERROR_FILE_NOT_FOUND);
3169    }
3170  } else {
3171    SetLastError(ERROR_BAD_ARGUMENTS);
3172  }
3173
3174  return result;
3175}
3176
3177
3178#ifndef HAVE_POLL
3179static int
3180poll(struct pollfd *pfd, unsigned int n, int milliseconds)
3181{
3182  struct timeval tv;
3183  fd_set set;
3184  unsigned int i;
3185  int result;
3186  SOCKET maxfd = 0;
3187
3188  memset(&tv, 0, sizeof(tv));
3189  tv.tv_sec = milliseconds / 1000;
3190  tv.tv_usec = (milliseconds % 1000) * 1000;
3191  FD_ZERO(&set);
3192
3193  for (i = 0; i < n; i++) {
3194    FD_SET((SOCKET)pfd[i].fd, &set);
3195    pfd[i].revents = 0;
3196
3197    if (pfd[i].fd > maxfd) {
3198      maxfd = pfd[i].fd;
3199    }
3200  }
3201
3202  if ((result = select((int)maxfd + 1, &set, NULL, NULL, &tv)) > 0) {
3203    for (i = 0; i < n; i++) {
3204      if (FD_ISSET(pfd[i].fd, &set)) {
3205        pfd[i].revents = POLLIN;
3206      }
3207    }
3208  }
3209
3210  return result;
3211}
3212#endif /* HAVE_POLL */
3213
3214#if defined(__MINGW32__)
3215/* Enable unused function warning again */
3216#pragma GCC diagnostic pop
3217#endif
3218
3219
3220static void
3221set_close_on_exec(SOCKET sock, struct mg_connection *conn /* may be null */)
3222{
3223  (void)conn; /* Unused. */
3224  (void)SetHandleInformation((HANDLE)(intptr_t)sock, HANDLE_FLAG_INHERIT, 0);
3225}
3226
3227
3228int
3229mg_start_thread(mg_thread_func_t f, void *p)
3230{
3231#if defined(USE_STACK_SIZE) && (USE_STACK_SIZE > 1)
3232  /* Compile-time option to control stack size, e.g. -DUSE_STACK_SIZE=16384
3233   */
3234  return ((_beginthread((void(__cdecl *)(void *))f, USE_STACK_SIZE, p)
3235           == ((uintptr_t)(-1L)))
3236              ? -1
3237              : 0);
3238#else
3239  return (
3240      (_beginthread((void(__cdecl *)(void *))f, 0, p) == ((uintptr_t)(-1L)))
3241          ? -1
3242          : 0);
3243#endif /* defined(USE_STACK_SIZE) && (USE_STACK_SIZE > 1) */
3244}
3245
3246
3247/* Start a thread storing the thread context. */
3248static int
3249mg_start_thread_with_id(unsigned(__stdcall *f)(void *),
3250                        void *p,
3251                        pthread_t *threadidptr)
3252{
3253  uintptr_t uip;
3254  HANDLE threadhandle;
3255  int result = -1;
3256
3257  uip = _beginthreadex(NULL, 0, (unsigned(__stdcall *)(void *))f, p, 0, NULL);
3258  threadhandle = (HANDLE)uip;
3259  if ((uip != (uintptr_t)(-1L)) && (threadidptr != NULL)) {
3260    *threadidptr = threadhandle;
3261    result = 0;
3262  }
3263
3264  return result;
3265}
3266
3267
3268/* Wait for a thread to finish. */
3269static int
3270mg_join_thread(pthread_t threadid)
3271{
3272  int result;
3273  DWORD dwevent;
3274
3275  result = -1;
3276  dwevent = WaitForSingleObject(threadid, INFINITE);
3277  if (dwevent == WAIT_FAILED) {
3278    DEBUG_TRACE("WaitForSingleObject() failed, error %d", ERRNO);
3279  } else {
3280    if (dwevent == WAIT_OBJECT_0) {
3281      CloseHandle(threadid);
3282      result = 0;
3283    }
3284  }
3285
3286  return result;
3287}
3288
3289#if !defined(NO_SSL_DL)
3290/* Create substitutes for POSIX functions in Win32. */
3291
3292#if defined(__MINGW32__)
3293/* Show no warning in case system functions are not used. */
3294#pragma GCC diagnostic push
3295#pragma GCC diagnostic ignored "-Wunused-function"
3296#endif
3297
3298
3299static HANDLE
3300dlopen(const char *dll_name, int flags)
3301{
3302  wchar_t wbuf[PATH_MAX];
3303  (void)flags;
3304  path_to_unicode(NULL, dll_name, wbuf, ARRAY_SIZE(wbuf));
3305  return LoadLibraryW(wbuf);
3306}
3307
3308
3309static int
3310dlclose(void *handle)
3311{
3312  int result;
3313
3314  if (FreeLibrary((HMODULE)handle) != 0) {
3315    result = 0;
3316  } else {
3317    result = -1;
3318  }
3319
3320  return result;
3321}
3322
3323
3324#if defined(__MINGW32__)
3325/* Enable unused function warning again */
3326#pragma GCC diagnostic pop
3327#endif
3328
3329#endif
3330
3331
3332#if !defined(NO_CGI)
3333#define SIGKILL (0)
3334
3335static int
3336kill(pid_t pid, int sig_num)
3337{
3338  (void)TerminateProcess((HANDLE)pid, (UINT)sig_num);
3339  (void)CloseHandle((HANDLE)pid);
3340  return 0;
3341}
3342
3343
3344static void
3345trim_trailing_whitespaces(char *s)
3346{
3347  char *e = s + strlen(s) - 1;
3348  while (e > s && isspace(*(unsigned char *)e)) {
3349    *e-- = '\0';
3350  }
3351}
3352
3353
3354static pid_t
3355spawn_process(struct mg_connection *conn,
3356              const char *prog,
3357              char *envblk,
3358              char *envp[],
3359              int fdin[2],
3360              int fdout[2],
3361              int fderr[2],
3362              const char *dir)
3363{
3364  HANDLE me;
3365  char *p, *interp, full_interp[PATH_MAX], full_dir[PATH_MAX],
3366      cmdline[PATH_MAX], buf[PATH_MAX];
3367  int truncated;
3368  struct file file = STRUCT_FILE_INITIALIZER;
3369  STARTUPINFOA si;
3370  PROCESS_INFORMATION pi = {0};
3371
3372  (void)envp;
3373
3374  memset(&si, 0, sizeof(si));
3375  si.cb = sizeof(si);
3376
3377  si.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
3378  si.wShowWindow = SW_HIDE;
3379
3380  me = GetCurrentProcess();
3381  DuplicateHandle(me,
3382                  (HANDLE)_get_osfhandle(fdin[0]),
3383                  me,
3384                  &si.hStdInput,
3385                  0,
3386                  TRUE,
3387                  DUPLICATE_SAME_ACCESS);
3388  DuplicateHandle(me,
3389                  (HANDLE)_get_osfhandle(fdout[1]),
3390                  me,
3391                  &si.hStdOutput,
3392                  0,
3393                  TRUE,
3394                  DUPLICATE_SAME_ACCESS);
3395  DuplicateHandle(me,
3396                  (HANDLE)_get_osfhandle(fderr[1]),
3397                  me,
3398                  &si.hStdError,
3399                  0,
3400                  TRUE,
3401                  DUPLICATE_SAME_ACCESS);
3402
3403  /* Mark handles that should not be inherited. See
3404   * https://msdn.microsoft.com/en-us/library/windows/desktop/ms682499%28v=vs.85%29.aspx
3405   */
3406  SetHandleInformation((HANDLE)_get_osfhandle(fdin[1]),
3407                       HANDLE_FLAG_INHERIT,
3408                       0);
3409  SetHandleInformation((HANDLE)_get_osfhandle(fdout[0]),
3410                       HANDLE_FLAG_INHERIT,
3411                       0);
3412  SetHandleInformation((HANDLE)_get_osfhandle(fderr[0]),
3413                       HANDLE_FLAG_INHERIT,
3414                       0);
3415
3416  /* If CGI file is a script, try to read the interpreter line */
3417  interp = conn->ctx->config[CGI_INTERPRETER];
3418  if (interp == NULL) {
3419    buf[0] = buf[1] = '\0';
3420
3421    /* Read the first line of the script into the buffer */
3422    mg_snprintf(
3423        conn, &truncated, cmdline, sizeof(cmdline), "%s/%s", dir, prog);
3424
3425    if (truncated) {
3426      pi.hProcess = (pid_t)-1;
3427      goto spawn_cleanup;
3428    }
3429
3430    if (mg_fopen(conn, cmdline, "r", &file)) {
3431      p = (char *)file.membuf;
3432      mg_fgets(buf, sizeof(buf), &file, &p);
3433      mg_fclose(&file);
3434      buf[sizeof(buf) - 1] = '\0';
3435    }
3436
3437    if (buf[0] == '#' && buf[1] == '!') {
3438      trim_trailing_whitespaces(buf + 2);
3439    } else {
3440      buf[2] = '\0';
3441    }
3442    interp = buf + 2;
3443  }
3444
3445  if (interp[0] != '\0') {
3446    GetFullPathNameA(interp, sizeof(full_interp), full_interp, NULL);
3447    interp = full_interp;
3448  }
3449  GetFullPathNameA(dir, sizeof(full_dir), full_dir, NULL);
3450
3451  if (interp[0] != '\0') {
3452    mg_snprintf(conn,
3453                &truncated,
3454                cmdline,
3455                sizeof(cmdline),
3456                "\"%s\" \"%s\\%s\"",
3457                interp,
3458                full_dir,
3459                prog);
3460  } else {
3461    mg_snprintf(conn,
3462                &truncated,
3463                cmdline,
3464                sizeof(cmdline),
3465                "\"%s\\%s\"",
3466                full_dir,
3467                prog);
3468  }
3469
3470  if (truncated) {
3471    pi.hProcess = (pid_t)-1;
3472    goto spawn_cleanup;
3473  }
3474
3475  DEBUG_TRACE("Running [%s]", cmdline);
3476  if (CreateProcessA(NULL,
3477                     cmdline,
3478                     NULL,
3479                     NULL,
3480                     TRUE,
3481                     CREATE_NEW_PROCESS_GROUP,
3482                     envblk,
3483                     NULL,
3484                     &si,
3485                     &pi) == 0) {
3486    mg_cry(
3487        conn, "%s: CreateProcess(%s): %ld", __func__, cmdline, (long)ERRNO);
3488    pi.hProcess = (pid_t)-1;
3489    /* goto spawn_cleanup; */
3490  }
3491
3492spawn_cleanup:
3493  (void)CloseHandle(si.hStdOutput);
3494  (void)CloseHandle(si.hStdError);
3495  (void)CloseHandle(si.hStdInput);
3496  if (pi.hThread != NULL) {
3497    (void)CloseHandle(pi.hThread);
3498  }
3499
3500  return (pid_t)pi.hProcess;
3501}
3502#endif /* !NO_CGI */
3503
3504
3505static int
3506set_non_blocking_mode(SOCKET sock)
3507{
3508  unsigned long on = 1;
3509  return ioctlsocket(sock, (long)FIONBIO, &on);
3510}
3511
3512#else
3513
3514static int
3515mg_stat(struct mg_connection *conn, const char *path, struct file *filep)
3516{
3517  struct stat st;
3518  if (!filep) {
3519    return 0;
3520  }
3521  memset(filep, 0, sizeof(*filep));
3522
3523  if (conn && is_file_in_memory(conn, path, filep)) {
3524    return 1;
3525  }
3526
3527    if (path && path[4] == 0 && memcmp(path, "www/", 4) == 0)
3528    {
3529        filep->size = 512;
3530        filep->is_directory = 1;
3531        return 1;
3532    }
3533
3534  if (0 == stat(path, &st)) {
3535    filep->size = (uint64_t)(st.st_size);
3536    filep->last_modified = st.st_mtime;
3537    filep->is_directory = S_ISDIR(st.st_mode);
3538    return 1;
3539  }
3540
3541  return 0;
3542}
3543
3544
3545static void
3546set_close_on_exec(SOCKET fd, struct mg_connection *conn /* may be null */)
3547{
3548  if (fcntl(fd, F_SETFD, FD_CLOEXEC) != 0) {
3549    if (conn) {
3550      mg_cry(conn,
3551             "%s: fcntl(F_SETFD FD_CLOEXEC) failed: %s",
3552             __func__,
3553             strerror(ERRNO));
3554    }
3555  }
3556}
3557
3558
3559int
3560mg_start_thread(mg_thread_func_t func, void *param)
3561{
3562  pthread_t thread_id;
3563  pthread_attr_t attr;
3564  int result;
3565
3566  (void)pthread_attr_init(&attr);
3567  (void)pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
3568
3569#if defined(USE_STACK_SIZE) && (USE_STACK_SIZE > 1)
3570  /* Compile-time option to control stack size,
3571   * e.g. -DUSE_STACK_SIZE=16384 */
3572  (void)pthread_attr_setstacksize(&attr, USE_STACK_SIZE);
3573#endif /* defined(USE_STACK_SIZE) && (USE_STACK_SIZE > 1) */
3574
3575  result = pthread_create(&thread_id, &attr, func, param);
3576  pthread_attr_destroy(&attr);
3577
3578  return result;
3579}
3580
3581
3582/* Start a thread storing the thread context. */
3583static int
3584mg_start_thread_with_id(mg_thread_func_t func,
3585                        void *param,
3586                        pthread_t *threadidptr)
3587{
3588  pthread_t thread_id;
3589  pthread_attr_t attr;
3590  int result;
3591
3592  (void)pthread_attr_init(&attr);
3593
3594#if defined(USE_STACK_SIZE) && (USE_STACK_SIZE > 1)
3595  /* Compile-time option to control stack size,
3596   * e.g. -DUSE_STACK_SIZE=16384 */
3597  (void)pthread_attr_setstacksize(&attr, USE_STACK_SIZE);
3598#endif /* defined(USE_STACK_SIZE) && USE_STACK_SIZE > 1 */
3599
3600  result = pthread_create(&thread_id, &attr, func, param);
3601  pthread_attr_destroy(&attr);
3602  if ((result == 0) && (threadidptr != NULL)) {
3603    *threadidptr = thread_id;
3604  }
3605  return result;
3606}
3607
3608
3609/* Wait for a thread to finish. */
3610static int
3611mg_join_thread(pthread_t threadid)
3612{
3613  int result;
3614
3615  result = pthread_join(threadid, NULL);
3616  return result;
3617}
3618
3619
3620#ifndef NO_CGI
3621static pid_t
3622spawn_process(struct mg_connection *conn,
3623              const char *prog,
3624              char *envblk,
3625              char *envp[],
3626              int fdin[2],
3627              int fdout[2],
3628              int fderr[2],
3629              const char *dir)
3630{
3631  pid_t pid;
3632  const char *interp;
3633
3634  (void)envblk;
3635
3636  if (conn == NULL) {
3637    return 0;
3638  }
3639
3640  if ((pid = fork()) == -1) {
3641    /* Parent */
3642    send_http_error(conn,
3643                    500,
3644                    "Error: Creating CGI process\nfork(): %s",
3645                    strerror(ERRNO));
3646  } else if (pid == 0) {
3647    /* Child */
3648    if (chdir(dir) != 0) {
3649      mg_cry(conn, "%s: chdir(%s): %s", __func__, dir, strerror(ERRNO));
3650    } else if (dup2(fdin[0], 0) == -1) {
3651      mg_cry(conn,
3652             "%s: dup2(%d, 0): %s",
3653             __func__,
3654             fdin[0],
3655             strerror(ERRNO));
3656    } else if (dup2(fdout[1], 1) == -1) {
3657      mg_cry(conn,
3658             "%s: dup2(%d, 1): %s",
3659             __func__,
3660             fdout[1],
3661             strerror(ERRNO));
3662    } else if (dup2(fderr[1], 2) == -1) {
3663      mg_cry(conn,
3664             "%s: dup2(%d, 2): %s",
3665             __func__,
3666             fderr[1],
3667             strerror(ERRNO));
3668    } else {
3669      /* Keep stderr and stdout in two different pipes.
3670       * Stdout will be sent back to the client,
3671       * stderr should go into a server error log. */
3672      (void)close(fdin[0]);
3673      (void)close(fdout[1]);
3674      (void)close(fderr[1]);
3675
3676      /* Close write end fdin and read end fdout and fderr */
3677      (void)close(fdin[1]);
3678      (void)close(fdout[0]);
3679      (void)close(fderr[0]);
3680
3681      /* After exec, all signal handlers are restored to their default
3682       * values, with one exception of SIGCHLD. According to
3683       * POSIX.1-2001 and Linux's implementation, SIGCHLD's handler will
3684       * leave unchanged after exec if it was set to be ignored. Restore
3685       * it to default action. */
3686      signal(SIGCHLD, SIG_DFL);
3687
3688      interp = conn->ctx->config[CGI_INTERPRETER];
3689      if (interp == NULL) {
3690        (void)execle(prog, prog, NULL, envp);
3691        mg_cry(conn,
3692               "%s: execle(%s): %s",
3693               __func__,
3694               prog,
3695               strerror(ERRNO));
3696      } else {
3697        (void)execle(interp, interp, prog, NULL, envp);
3698        mg_cry(conn,
3699               "%s: execle(%s %s): %s",
3700               __func__,
3701               interp,
3702               prog,
3703               strerror(ERRNO));
3704      }
3705    }
3706    exit(EXIT_FAILURE);
3707  }
3708
3709  return pid;
3710}
3711#endif /* !NO_CGI */
3712
3713
3714static int
3715set_non_blocking_mode(SOCKET sock)
3716{
3717  int flags;
3718
3719  flags = fcntl(sock, F_GETFL, 0);
3720  (void)fcntl(sock, F_SETFL, flags | O_NONBLOCK);
3721
3722  return 0;
3723}
3724#endif /* _WIN32 */
3725/* End of initial operating system specific define block. */
3726
3727
3728/* Get a random number (independent of C rand function) */
3729static uint64_t
3730get_random(void)
3731{
3732  static uint64_t lfsr = 0; /* Linear feedback shift register */
3733  static uint64_t lcg = 0;  /* Linear congruential generator */
3734  struct timespec now;
3735
3736  memset(&now, 0, sizeof(now));
3737  clock_gettime(CLOCK_MONOTONIC, &now);
3738
3739  if (lfsr == 0) {
3740    /* lfsr will be only 0 if has not been initialized,
3741     * so this code is called only once. */
3742    lfsr = (((uint64_t)now.tv_sec) << 21) ^ ((uint64_t)now.tv_nsec)
3743           ^ ((uint64_t)(ptrdiff_t)&now) ^ (((uint64_t)time(NULL)) << 33);
3744    lcg = (((uint64_t)now.tv_sec) << 25) + (uint64_t)now.tv_nsec
3745          + (uint64_t)(ptrdiff_t)&now;
3746  } else {
3747    /* Get the next step of both random number generators. */
3748    lfsr = (lfsr >> 1)
3749           | ((((lfsr >> 0) ^ (lfsr >> 1) ^ (lfsr >> 3) ^ (lfsr >> 4)) & 1)
3750              << 63);
3751    lcg = lcg * 6364136223846793005 + 1442695040888963407;
3752  }
3753
3754  /* Combining two pseudo-random number generators and a high resolution part
3755   * of the current server time will make it hard (impossible?) to guess the
3756   * next number. */
3757  return (lfsr ^ lcg ^ (uint64_t)now.tv_nsec);
3758}
3759
3760
3761/* Write data to the IO channel - opened file descriptor, socket or SSL
3762 * descriptor. Return number of bytes written. */
3763static int
3764push(struct mg_context *ctx,
3765     FILE *fp,
3766     SOCKET sock,
3767     SSL *ssl,
3768     const char *buf,
3769     int len,
3770     double timeout)
3771{
3772  struct timespec start, now;
3773  int n, err;
3774
3775#ifdef _WIN32
3776  typedef int len_t;
3777#else
3778  typedef size_t len_t;
3779#endif
3780
3781  if (timeout > 0) {
3782    memset(&start, 0, sizeof(start));
3783    memset(&now, 0, sizeof(now));
3784    clock_gettime(CLOCK_MONOTONIC, &start);
3785  }
3786
3787  if (ctx == NULL) {
3788    return -1;
3789  }
3790
3791#ifdef NO_SSL
3792  if (ssl) {
3793    return -1;
3794  }
3795#endif
3796
3797  do {
3798
3799#ifndef NO_SSL
3800    if (ssl != NULL) {
3801      n = SSL_write(ssl, buf, len);
3802      if (n <= 0) {
3803        err = SSL_get_error(ssl, n);
3804        if ((err == 5 /* SSL_ERROR_SYSCALL */) && (n == -1)) {
3805          err = ERRNO;
3806        } else {
3807          DEBUG_TRACE("SSL_write() failed, error %d", err);
3808          return -1;
3809        }
3810      } else {
3811        err = 0;
3812      }
3813    } else
3814#endif
3815        if (fp != NULL) {
3816      n = (int)fwrite(buf, 1, (size_t)len, fp);
3817      if (ferror(fp)) {
3818        n = -1;
3819        err = ERRNO;
3820      } else {
3821        err = 0;
3822      }
3823    } else {
3824      n = (int)send(sock, buf, (len_t)len, MSG_NOSIGNAL);
3825      err = (n < 0) ? ERRNO : 0;
3826    }
3827
3828    if (ctx->stop_flag) {
3829      return -1;
3830    }
3831
3832    if ((n > 0) || (n == 0 && len == 0)) {
3833      /* some data has been read, or no data was requested */
3834      return n;
3835    }
3836    if (n == 0) {
3837      /* shutdown of the socket at client side */
3838      return -1;
3839    }
3840    if (n < 0) {
3841      /* socket error - check errno */
3842      DEBUG_TRACE("send() failed, error %d", err);
3843
3844      /* TODO: error handling depending on the error code.
3845       * These codes are different between Windows and Linux.
3846       */
3847      return -1;
3848    }
3849
3850    /* This code is not reached in the moment.
3851     * ==> Fix the TODOs above first. */
3852
3853    if (timeout > 0) {
3854      clock_gettime(CLOCK_MONOTONIC, &now);
3855    }
3856
3857  } while ((timeout <= 0) || (mg_difftimespec(&now, &start) <= timeout));
3858
3859  (void)err; /* Avoid unused warning if NO_SSL is set and DEBUG_TRACE is not
3860                used */
3861
3862  return -1;
3863}
3864
3865
3866static int64_t
3867push_all(struct mg_context *ctx,
3868         FILE *fp,
3869         SOCKET sock,
3870         SSL *ssl,
3871         const char *buf,
3872         int64_t len)
3873{
3874  double timeout = -1.0;
3875  int64_t n, nwritten = 0;
3876
3877  if (ctx == NULL) {
3878    return -1;
3879  }
3880
3881  if (ctx->config[REQUEST_TIMEOUT]) {
3882    timeout = atoi(ctx->config[REQUEST_TIMEOUT]) / 1000.0;
3883  }
3884
3885  while (len > 0 && ctx->stop_flag == 0) {
3886    n = push(ctx, fp, sock, ssl, buf + nwritten, (int)len, timeout);
3887    if (n < 0) {
3888      if (nwritten == 0) {
3889        nwritten = n; /* Propagate the error */
3890      }
3891      break;
3892    } else if (n == 0) {
3893      break; /* No more data to write */
3894    } else {
3895      nwritten += n;
3896      len -= n;
3897    }
3898  }
3899
3900  return nwritten;
3901}
3902
3903
3904/* Read from IO channel - opened file descriptor, socket, or SSL descriptor.
3905 * Return negative value on error, or number of bytes read on success. */
3906static int
3907pull(FILE *fp, struct mg_connection *conn, char *buf, int len, double timeout)
3908{
3909  int nread, err;
3910  struct timespec start, now;
3911
3912#ifdef _WIN32
3913  typedef int len_t;
3914#else
3915  typedef size_t len_t;
3916#endif
3917
3918  if (timeout > 0) {
3919    memset(&start, 0, sizeof(start));
3920    memset(&now, 0, sizeof(now));
3921    clock_gettime(CLOCK_MONOTONIC, &start);
3922  }
3923
3924  do {
3925    if (fp != NULL) {
3926      /* Use read() instead of fread(), because if we're reading from the
3927       * CGI pipe, fread() may block until IO buffer is filled up. We
3928       * cannot afford to block and must pass all read bytes immediately
3929       * to the client. */
3930      nread = (int)read(fileno(fp), buf, (size_t)len);
3931      err = (nread < 0) ? ERRNO : 0;
3932
3933#ifndef NO_SSL
3934    } else if (conn->ssl != NULL) {
3935      nread = SSL_read(conn->ssl, buf, len);
3936      if (nread <= 0) {
3937        err = SSL_get_error(conn->ssl, nread);
3938        if ((err == 5 /* SSL_ERROR_SYSCALL */) && (nread == -1)) {
3939          err = ERRNO;
3940        } else {
3941          DEBUG_TRACE("SSL_read() failed, error %d", err);
3942          return -1;
3943        }
3944      } else {
3945        err = 0;
3946      }
3947#endif
3948
3949    } else {
3950      nread = (int)recv(conn->client.sock, buf, (len_t)len, 0);
3951      err = (nread < 0) ? ERRNO : 0;
3952    }
3953
3954    if (conn->ctx->stop_flag) {
3955      return -1;
3956    }
3957
3958    if ((nread > 0) || (nread == 0 && len == 0)) {
3959      /* some data has been read, or no data was requested */
3960      return nread;
3961    }
3962    if (nread == 0) {
3963      /* shutdown of the socket at client side */
3964      return -1;
3965    }
3966    if (nread < 0) {
3967/* socket error - check errno */
3968#ifdef _WIN32
3969      if (err == WSAEWOULDBLOCK) {
3970        /* standard case if called from close_socket_gracefully */
3971        return -1;
3972      } else if (err == WSAETIMEDOUT) {
3973        /* timeout is handled by the while loop  */
3974      } else {
3975        DEBUG_TRACE("recv() failed, error %d", err);
3976        return -1;
3977      }
3978#else
3979      /* TODO: POSIX returns either EAGAIN or EWOULDBLOCK in both cases,
3980       * if the timeout is reached and if the socket was set to non-
3981       * blocking in close_socket_gracefully, so we can not distinguish
3982       * here. We have to wait for the timeout in both cases for now.
3983       */
3984      if (err == EAGAIN || err == EWOULDBLOCK || err == EINTR) {
3985        /* EAGAIN/EWOULDBLOCK:
3986         * standard case if called from close_socket_gracefully
3987         * => should return -1 */
3988        /* or timeout occured
3989         * => the code must stay in the while loop */
3990
3991        /* EINTR can be generated on a socket with a timeout set even
3992         * when SA_RESTART is effective for all relevant signals
3993         * (see signal(7)).
3994         * => stay in the while loop */
3995      } else {
3996        DEBUG_TRACE("recv() failed, error %d", err);
3997        return -1;
3998      }
3999#endif
4000    }
4001    if (timeout > 0) {
4002      clock_gettime(CLOCK_MONOTONIC, &now);
4003    }
4004  } while ((timeout <= 0) || (mg_difftimespec(&now, &start) <= timeout));
4005
4006  /* Timeout occured, but no data available. */
4007  return -1;
4008}
4009
4010
4011static int
4012pull_all(FILE *fp, struct mg_connection *conn, char *buf, int len)
4013{
4014  int n, nread = 0;
4015  double timeout = -1.0;
4016
4017  if (conn->ctx->config[REQUEST_TIMEOUT]) {
4018    timeout = atoi(conn->ctx->config[REQUEST_TIMEOUT]) / 1000.0;
4019  }
4020
4021  while (len > 0 && conn->ctx->stop_flag == 0) {
4022    n = pull(fp, conn, buf + nread, len, timeout);
4023    if (n < 0) {
4024      if (nread == 0) {
4025        nread = n; /* Propagate the error */
4026      }
4027      break;
4028    } else if (n == 0) {
4029      break; /* No more data to read */
4030    } else {
4031      conn->consumed_content += n;
4032      nread += n;
4033      len -= n;
4034    }
4035  }
4036
4037  return nread;
4038}
4039
4040
4041static void
4042discard_unread_request_data(struct mg_connection *conn)
4043{
4044  char buf[MG_BUF_LEN];
4045  size_t to_read;
4046  int nread;
4047
4048  if (conn == NULL) {
4049    return;
4050  }
4051
4052  to_read = sizeof(buf);
4053
4054  if (conn->is_chunked) {
4055    /* Chunked encoding: 1=chunk not read completely, 2=chunk read
4056     * completely */
4057    while (conn->is_chunked == 1) {
4058      nread = mg_read(conn, buf, to_read);
4059      if (nread <= 0) {
4060        break;
4061      }
4062    }
4063
4064  } else {
4065    /* Not chunked: content length is known */
4066    while (conn->consumed_content < conn->content_len) {
4067      if (to_read
4068          > (size_t)(conn->content_len - conn->consumed_content)) {
4069        to_read = (size_t)(conn->content_len - conn->consumed_content);
4070      }
4071
4072      nread = mg_read(conn, buf, to_read);
4073      if (nread <= 0) {
4074        break;
4075      }
4076    }
4077  }
4078}
4079
4080
4081static int
4082mg_read_inner(struct mg_connection *conn, void *buf, size_t len)
4083{
4084  int64_t n, buffered_len, nread;
4085  int64_t len64 =
4086      (int64_t)(len > INT_MAX ? INT_MAX : len); /* since the return value is
4087                                                 * int, we may not read more
4088                                                 * bytes */
4089  const char *body;
4090
4091  if (conn == NULL) {
4092    return 0;
4093  }
4094
4095  /* If Content-Length is not set for a PUT or POST request, read until
4096   * socket is closed */
4097  if (conn->consumed_content == 0 && conn->content_len == -1) {
4098    conn->content_len = INT64_MAX;
4099    conn->must_close = 1;
4100  }
4101
4102  nread = 0;
4103  if (conn->consumed_content < conn->content_len) {
4104    /* Adjust number of bytes to read. */
4105    int64_t left_to_read = conn->content_len - conn->consumed_content;
4106    if (left_to_read < len64) {
4107      /* Do not read more than the total content length of the request.
4108       */
4109      len64 = left_to_read;
4110    }
4111
4112    /* Return buffered data */
4113    buffered_len = (int64_t)(conn->data_len) - (int64_t)conn->request_len
4114                   - conn->consumed_content;
4115    if (buffered_len > 0) {
4116      if (len64 < buffered_len) {
4117        buffered_len = len64;
4118      }
4119      body = conn->buf + conn->request_len + conn->consumed_content;
4120      memcpy(buf, body, (size_t)buffered_len);
4121      len64 -= buffered_len;
4122      conn->consumed_content += buffered_len;
4123      nread += buffered_len;
4124      buf = (char *)buf + buffered_len;
4125    }
4126
4127    /* We have returned all buffered data. Read new data from the remote
4128     * socket.
4129     */
4130    if ((n = pull_all(NULL, conn, (char *)buf, (int)len64)) >= 0) {
4131      nread += n;
4132    } else {
4133      nread = (nread > 0 ? nread : n);
4134    }
4135  }
4136  return (int)nread;
4137}
4138
4139
4140static char
4141mg_getc(struct mg_connection *conn)
4142{
4143  char c;
4144  if (conn == NULL) {
4145    return 0;
4146  }
4147  conn->content_len++;
4148  if (mg_read_inner(conn, &c, 1) <= 0) {
4149    return (char)0;
4150  }
4151  return c;
4152}
4153
4154
4155int
4156mg_read(struct mg_connection *conn, void *buf, size_t len)
4157{
4158  if (len > INT_MAX) {
4159    len = INT_MAX;
4160  }
4161
4162  if (conn == NULL) {
4163    return 0;
4164  }
4165
4166  if (conn->is_chunked) {
4167    size_t all_read = 0;
4168
4169    while (len > 0) {
4170
4171      if (conn->is_chunked == 2) {
4172        /* No more data left to read */
4173        return 0;
4174      }
4175
4176      if (conn->chunk_remainder) {
4177        /* copy from the remainder of the last received chunk */
4178        long read_ret;
4179        size_t read_now =
4180            ((conn->chunk_remainder > len) ? (len)
4181                                           : (conn->chunk_remainder));
4182
4183        conn->content_len += (int)read_now;
4184        read_ret =
4185            mg_read_inner(conn, (char *)buf + all_read, read_now);
4186        all_read += (size_t)read_ret;
4187
4188        conn->chunk_remainder -= read_now;
4189        len -= read_now;
4190
4191        if (conn->chunk_remainder == 0) {
4192          /* the rest of the data in the current chunk has been read
4193           */
4194          if ((mg_getc(conn) != '\r') || (mg_getc(conn) != '\n')) {
4195            /* Protocol violation */
4196            return -1;
4197          }
4198        }
4199
4200      } else {
4201        /* fetch a new chunk */
4202        int i = 0;
4203        char lenbuf[64];
4204        char *end = 0;
4205        unsigned long chunkSize = 0;
4206
4207        for (i = 0; i < ((int)sizeof(lenbuf) - 1); i++) {
4208          lenbuf[i] = mg_getc(conn);
4209          if (i > 0 && lenbuf[i] == '\r' && lenbuf[i - 1] != '\r') {
4210            continue;
4211          }
4212          if (i > 1 && lenbuf[i] == '\n' && lenbuf[i - 1] == '\r') {
4213            lenbuf[i + 1] = 0;
4214            chunkSize = strtoul(lenbuf, &end, 16);
4215            if (chunkSize == 0) {
4216              /* regular end of content */
4217              conn->is_chunked = 2;
4218            }
4219            break;
4220          }
4221          if (!isalnum(lenbuf[i])) {
4222            /* illegal character for chunk length */
4223            return -1;
4224          }
4225        }
4226        if ((end == NULL) || (*end != '\r')) {
4227          /* chunksize not set correctly */
4228          return -1;
4229        }
4230        if (chunkSize == 0) {
4231          break;
4232        }
4233
4234        conn->chunk_remainder = chunkSize;
4235      }
4236    }
4237
4238    return (int)all_read;
4239  }
4240  return mg_read_inner(conn, buf, len);
4241}
4242
4243
4244int
4245mg_write(struct mg_connection *conn, const void *buf, size_t len)
4246{
4247  time_t now;
4248  int64_t n, total, allowed;
4249
4250  if (conn == NULL) {
4251    return 0;
4252  }
4253
4254  if (conn->throttle > 0) {
4255    if ((now = time(NULL)) != conn->last_throttle_time) {
4256      conn->last_throttle_time = now;
4257      conn->last_throttle_bytes = 0;
4258    }
4259    allowed = conn->throttle - conn->last_throttle_bytes;
4260    if (allowed > (int64_t)len) {
4261      allowed = (int64_t)len;
4262    }
4263    if ((total = push_all(conn->ctx,
4264                          NULL,
4265                          conn->client.sock,
4266                          conn->ssl,
4267                          (const char *)buf,
4268                          (int64_t)allowed)) == allowed) {
4269      buf = (const char *)buf + total;
4270      conn->last_throttle_bytes += total;
4271      while (total < (int64_t)len && conn->ctx->stop_flag == 0) {
4272        allowed = conn->throttle > (int64_t)len - total
4273                      ? (int64_t)len - total
4274                      : conn->throttle;
4275        if ((n = push_all(conn->ctx,
4276                          NULL,
4277                          conn->client.sock,
4278                          conn->ssl,
4279                          (const char *)buf,
4280                          (int64_t)allowed)) != allowed) {
4281          break;
4282        }
4283        sleep(1);
4284        conn->last_throttle_bytes = allowed;
4285        conn->last_throttle_time = time(NULL);
4286        buf = (const char *)buf + n;
4287        total += n;
4288      }
4289    }
4290  } else {
4291    total = push_all(conn->ctx,
4292                     NULL,
4293                     conn->client.sock,
4294                     conn->ssl,
4295                     (const char *)buf,
4296                     (int64_t)len);
4297  }
4298  return (int)total;
4299}
4300
4301
4302/* Alternative alloc_vprintf() for non-compliant C runtimes */
4303static int
4304alloc_vprintf2(char **buf, const char *fmt, va_list ap)
4305{
4306  va_list ap_copy;
4307  size_t size = MG_BUF_LEN / 4;
4308  int len = -1;
4309
4310  *buf = NULL;
4311  while (len < 0) {
4312    if (*buf) {
4313      mg_free(*buf);
4314    }
4315
4316    size *= 4;
4317    *buf = (char *)mg_malloc(size);
4318    if (!*buf) {
4319      break;
4320    }
4321
4322    va_copy(ap_copy, ap);
4323    len = vsnprintf_impl(*buf, size - 1, fmt, ap_copy);
4324    va_end(ap_copy);
4325    (*buf)[size - 1] = 0;
4326  }
4327
4328  return len;
4329}
4330
4331
4332/* Print message to buffer. If buffer is large enough to hold the message,
4333 * return buffer. If buffer is to small, allocate large enough buffer on heap,
4334 * and return allocated buffer. */
4335static int
4336alloc_vprintf(char **out_buf,
4337              char *prealloc_buf,
4338              size_t prealloc_size,
4339              const char *fmt,
4340              va_list ap)
4341{
4342  va_list ap_copy;
4343  int len;
4344
4345  /* Windows is not standard-compliant, and vsnprintf() returns -1 if
4346   * buffer is too small. Also, older versions of msvcrt.dll do not have
4347   * _vscprintf().  However, if size is 0, vsnprintf() behaves correctly.
4348   * Therefore, we make two passes: on first pass, get required message
4349   * length.
4350   * On second pass, actually print the message. */
4351  va_copy(ap_copy, ap);
4352  len = vsnprintf_impl(NULL, 0, fmt, ap_copy);
4353  va_end(ap_copy);
4354
4355  if (len < 0) {
4356    /* C runtime is not standard compliant, vsnprintf() returned -1.
4357     * Switch to alternative code path that uses incremental allocations.
4358    */
4359    va_copy(ap_copy, ap);
4360    len = alloc_vprintf2(out_buf, fmt, ap);
4361    va_end(ap_copy);
4362
4363  } else if ((size_t)(len) >= prealloc_size) {
4364    /* The pre-allocated buffer not large enough. */
4365    /* Allocate a new buffer. */
4366    *out_buf = (char *)mg_malloc((size_t)(len) + 1);
4367    if (!*out_buf) {
4368      /* Allocation failed. Return -1 as "out of memory" error. */
4369      return -1;
4370    }
4371    /* Buffer allocation successful. Store the string there. */
4372    va_copy(ap_copy, ap);
4373    IGNORE_UNUSED_RESULT(
4374        vsnprintf_impl(*out_buf, (size_t)(len) + 1, fmt, ap_copy));
4375    va_end(ap_copy);
4376
4377  } else {
4378    /* The pre-allocated buffer is large enough.
4379     * Use it to store the string and return the address. */
4380    va_copy(ap_copy, ap);
4381    IGNORE_UNUSED_RESULT(
4382        vsnprintf_impl(prealloc_buf, prealloc_size, fmt, ap_copy));
4383    va_end(ap_copy);
4384    *out_buf = prealloc_buf;
4385  }
4386
4387  return len;
4388}
4389
4390
4391static int
4392mg_vprintf(struct mg_connection *conn, const char *fmt, va_list ap)
4393{
4394  char mem[MG_BUF_LEN];
4395  char *buf = NULL;
4396  int len;
4397
4398  if ((len = alloc_vprintf(&buf, mem, sizeof(mem), fmt, ap)) > 0) {
4399    len = mg_write(conn, buf, (size_t)len);
4400  }
4401  if (buf != mem && buf != NULL) {
4402    mg_free(buf);
4403  }
4404
4405  return len;
4406}
4407
4408
4409int
4410mg_printf(struct mg_connection *conn, const char *fmt, ...)
4411{
4412  va_list ap;
4413  int result;
4414
4415  va_start(ap, fmt);
4416  result = mg_vprintf(conn, fmt, ap);
4417  va_end(ap);
4418
4419  return result;
4420}
4421
4422
4423int
4424mg_url_decode(const char *src,
4425              int src_len,
4426              char *dst,
4427              int dst_len,
4428              int is_form_url_encoded)
4429{
4430  int i, j, a, b;
4431#define HEXTOI(x) (isdigit(x) ? x - '0' : x - 'W')
4432
4433  for (i = j = 0; i < src_len && j < dst_len - 1; i++, j++) {
4434    if (i < src_len - 2 && src[i] == '%'
4435        && isxdigit(*(const unsigned char *)(src + i + 1))
4436        && isxdigit(*(const unsigned char *)(src + i + 2))) {
4437      a = tolower(*(const unsigned char *)(src + i + 1));
4438      b = tolower(*(const unsigned char *)(src + i + 2));
4439      dst[j] = (char)((HEXTOI(a) << 4) | HEXTOI(b));
4440      i += 2;
4441    } else if (is_form_url_encoded && src[i] == '+') {
4442      dst[j] = ' ';
4443    } else {
4444      dst[j] = src[i];
4445    }
4446  }
4447
4448  dst[j] = '\0'; /* Null-terminate the destination */
4449
4450  return i >= src_len ? j : -1;
4451}
4452
4453
4454int
4455mg_get_var(const char *data,
4456           size_t data_len,
4457           const char *name,
4458           char *dst,
4459           size_t dst_len)
4460{
4461  return mg_get_var2(data, data_len, name, dst, dst_len, 0);
4462}
4463
4464
4465int
4466mg_get_var2(const char *data,
4467            size_t data_len,
4468            const char *name,
4469            char *dst,
4470            size_t dst_len,
4471            size_t occurrence)
4472{
4473  const char *p, *e, *s;
4474  size_t name_len;
4475  int len;
4476
4477  if (dst == NULL || dst_len == 0) {
4478    len = -2;
4479  } else if (data == NULL || name == NULL || data_len == 0) {
4480    len = -1;
4481    dst[0] = '\0';
4482  } else {
4483    name_len = strlen(name);
4484    e = data + data_len;
4485    len = -1;
4486    dst[0] = '\0';
4487
4488    /* data is "var1=val1&var2=val2...". Find variable first */
4489    for (p = data; p + name_len < e; p++) {
4490      if ((p == data || p[-1] == '&') && p[name_len] == '='
4491          && !mg_strncasecmp(name, p, name_len) && 0 == occurrence--) {
4492        /* Point p to variable value */
4493        p += name_len + 1;
4494
4495        /* Point s to the end of the value */
4496        s = (const char *)memchr(p, '&', (size_t)(e - p));
4497        if (s == NULL) {
4498          s = e;
4499        }
4500        /* assert(s >= p); */
4501        if (s < p) {
4502          return -3;
4503        }
4504
4505        /* Decode variable into destination buffer */
4506        len = mg_url_decode(p, (int)(s - p), dst, (int)dst_len, 1);
4507
4508        /* Redirect error code from -1 to -2 (destination buffer too
4509         * small). */
4510        if (len == -1) {
4511          len = -2;
4512        }
4513        break;
4514      }
4515    }
4516  }
4517
4518  return len;
4519}
4520
4521
4522int
4523mg_get_cookie(const char *cookie_header,
4524              const char *var_name,
4525              char *dst,
4526              size_t dst_size)
4527{
4528  const char *s, *p, *end;
4529  int name_len, len = -1;
4530
4531  if (dst == NULL || dst_size == 0) {
4532    len = -2;
4533  } else if (var_name == NULL || (s = cookie_header) == NULL) {
4534    len = -1;
4535    dst[0] = '\0';
4536  } else {
4537    name_len = (int)strlen(var_name);
4538    end = s + strlen(s);
4539    dst[0] = '\0';
4540
4541    for (; (s = mg_strcasestr(s, var_name)) != NULL; s += name_len) {
4542      if (s[name_len] == '=') {
4543        s += name_len + 1;
4544        if ((p = strchr(s, ' ')) == NULL) {
4545          p = end;
4546        }
4547        if (p[-1] == ';') {
4548          p--;
4549        }
4550        if (*s == '"' && p[-1] == '"' && p > s + 1) {
4551          s++;
4552          p--;
4553        }
4554        if ((size_t)(p - s) < dst_size) {
4555          len = (int)(p - s);
4556          mg_strlcpy(dst, s, (size_t)len + 1);
4557        } else {
4558          len = -3;
4559        }
4560        break;
4561      }
4562    }
4563  }
4564  return len;
4565}
4566
4567
4568#if defined(USE_WEBSOCKET) || defined(USE_LUA)
4569static void
4570base64_encode(const unsigned char *src, int src_len, char *dst)
4571{
4572  static const char *b64 =
4573      "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
4574  int i, j, a, b, c;
4575
4576  for (i = j = 0; i < src_len; i += 3) {
4577    a = src[i];
4578    b = i + 1 >= src_len ? 0 : src[i + 1];
4579    c = i + 2 >= src_len ? 0 : src[i + 2];
4580
4581    dst[j++] = b64[a >> 2];
4582    dst[j++] = b64[((a & 3) << 4) | (b >> 4)];
4583    if (i + 1 < src_len) {
4584      dst[j++] = b64[(b & 15) << 2 | (c >> 6)];
4585    }
4586    if (i + 2 < src_len) {
4587      dst[j++] = b64[c & 63];
4588    }
4589  }
4590  while (j % 4 != 0) {
4591    dst[j++] = '=';
4592  }
4593  dst[j++] = '\0';
4594}
4595#endif
4596
4597
4598#if defined(USE_LUA)
4599static unsigned char
4600b64reverse(char letter)
4601{
4602  if (letter >= 'A' && letter <= 'Z') {
4603    return letter - 'A';
4604  }
4605  if (letter >= 'a' && letter <= 'z') {
4606    return letter - 'a' + 26;
4607  }
4608  if (letter >= '0' && letter <= '9') {
4609    return letter - '0' + 52;
4610  }
4611  if (letter == '+') {
4612    return 62;
4613  }
4614  if (letter == '/') {
4615    return 63;
4616  }
4617  if (letter == '=') {
4618    return 255; /* normal end */
4619  }
4620  return 254; /* error */
4621}
4622
4623
4624static int
4625base64_decode(const unsigned char *src, int src_len, char *dst, size_t *dst_len)
4626{
4627  int i;
4628  unsigned char a, b, c, d;
4629
4630  *dst_len = 0;
4631
4632  for (i = 0; i < src_len; i += 4) {
4633    a = b64reverse(src[i]);
4634    if (a >= 254) {
4635      return i;
4636    }
4637
4638    b = b64reverse(i + 1 >= src_len ? 0 : src[i + 1]);
4639    if (b >= 254) {
4640      return i + 1;
4641    }
4642
4643    c = b64reverse(i + 2 >= src_len ? 0 : src[i + 2]);
4644    if (c == 254) {
4645      return i + 2;
4646    }
4647
4648    d = b64reverse(i + 3 >= src_len ? 0 : src[i + 3]);
4649    if (d == 254) {
4650      return i + 3;
4651    }
4652
4653    dst[(*dst_len)++] = (a << 2) + (b >> 4);
4654    if (c != 255) {
4655      dst[(*dst_len)++] = (b << 4) + (c >> 2);
4656      if (d != 255) {
4657        dst[(*dst_len)++] = (c << 6) + d;
4658      }
4659    }
4660  }
4661  return -1;
4662}
4663#endif
4664
4665
4666static int
4667is_put_or_delete_method(const struct mg_connection *conn)
4668{
4669  if (conn) {
4670    const char *s = conn->request_info.request_method;
4671    return s != NULL && (!strcmp(s, "PUT") || !strcmp(s, "DELETE")
4672                         || !strcmp(s, "MKCOL") || !strcmp(s, "PATCH"));
4673  }
4674  return 0;
4675}
4676
4677
4678static void
4679interpret_uri(struct mg_connection *conn,   /* in: request (must be valid) */
4680              char *filename,               /* out: filename */
4681              size_t filename_buf_len,      /* in: size of filename buffer */
4682              struct file *filep,           /* out: file structure */
4683              int *is_found,                /* out: file is found (directly) */
4684              int *is_script_resource,      /* out: handled by a script? */
4685              int *is_websocket_request,    /* out: websocket connetion? */
4686              int *is_put_or_delete_request /* out: put/delete a file? */
4687              )
4688{
4689/* TODO (high): Restructure this function */
4690
4691#if !defined(NO_FILES)
4692  const char *uri = conn->request_info.local_uri;
4693  const char *root = conn->ctx->config[DOCUMENT_ROOT];
4694  const char *rewrite;
4695  struct vec a, b;
4696  int match_len;
4697  char gz_path[PATH_MAX];
4698  char const *accept_encoding;
4699  int truncated;
4700#if !defined(NO_CGI) || defined(USE_LUA)
4701  char *p;
4702#endif
4703#else
4704  (void)filename_buf_len; /* unused if NO_FILES is defined */
4705#endif
4706
4707  memset(filep, 0, sizeof(*filep));
4708  *filename = 0;
4709  *is_found = 0;
4710  *is_script_resource = 0;
4711  *is_put_or_delete_request = is_put_or_delete_method(conn);
4712
4713#if defined(USE_WEBSOCKET)
4714  *is_websocket_request = is_websocket_protocol(conn);
4715#if !defined(NO_FILES)
4716  if (*is_websocket_request && conn->ctx->config[WEBSOCKET_ROOT]) {
4717    root = conn->ctx->config[WEBSOCKET_ROOT];
4718  }
4719#endif /* !NO_FILES */
4720#else  /* USE_WEBSOCKET */
4721  *is_websocket_request = 0;
4722#endif /* USE_WEBSOCKET */
4723
4724#if !defined(NO_FILES)
4725  /* Note that root == NULL is a regular use case here. This occurs,
4726   * if all requests are handled by callbacks, so the WEBSOCKET_ROOT
4727   * config is not required. */
4728  if (root == NULL) {
4729    /* all file related outputs have already been set to 0, just return
4730     */
4731    return;
4732  }
4733
4734  /* Using buf_len - 1 because memmove() for PATH_INFO may shift part
4735   * of the path one byte on the right.
4736   * If document_root is NULL, leave the file empty. */
4737  mg_snprintf(
4738      conn, &truncated, filename, filename_buf_len - 1, "%s%s", root, uri);
4739
4740  if (truncated) {
4741    goto interpret_cleanup;
4742  }
4743
4744  rewrite = conn->ctx->config[REWRITE];
4745  while ((rewrite = next_option(rewrite, &a, &b)) != NULL) {
4746    if ((match_len = match_prefix(a.ptr, a.len, uri)) > 0) {
4747      mg_snprintf(conn,
4748                  &truncated,
4749                  filename,
4750                  filename_buf_len - 1,
4751                  "%.*s%s",
4752                  (int)b.len,
4753                  b.ptr,
4754                  uri + match_len);
4755      break;
4756    }
4757  }
4758
4759  if (truncated) {
4760    goto interpret_cleanup;
4761  }
4762
4763  /* Local file path and name, corresponding to requested URI
4764   * is now stored in "filename" variable. */
4765  if (mg_stat(conn, filename, filep)) {
4766#if !defined(NO_CGI) || defined(USE_LUA) || defined(USE_DUKTAPE)
4767    /* File exists. Check if it is a script type. */
4768    if (0
4769#if !defined(NO_CGI)
4770        || match_prefix(conn->ctx->config[CGI_EXTENSIONS],
4771                        strlen(conn->ctx->config[CGI_EXTENSIONS]),
4772                        filename) > 0
4773#endif
4774#if defined(USE_LUA)
4775        || match_prefix(conn->ctx->config[LUA_SCRIPT_EXTENSIONS],
4776                        strlen(conn->ctx->config[LUA_SCRIPT_EXTENSIONS]),
4777                        filename) > 0
4778#endif
4779#if defined(USE_DUKTAPE)
4780        || match_prefix(conn->ctx->config[DUKTAPE_SCRIPT_EXTENSIONS],
4781                        strlen(
4782                            conn->ctx->config[DUKTAPE_SCRIPT_EXTENSIONS]),
4783                        filename) > 0
4784#endif
4785        ) {
4786      /* The request addresses a CGI script or a Lua script. The URI
4787       * corresponds to the script itself (like /path/script.cgi),
4788       * and there is no additional resource path
4789       * (like /path/script.cgi/something).
4790       * Requests that modify (replace or delete) a resource, like
4791       * PUT and DELETE requests, should replace/delete the script
4792       * file.
4793       * Requests that read or write from/to a resource, like GET and
4794       * POST requests, should call the script and return the
4795       * generated response. */
4796      *is_script_resource = !*is_put_or_delete_request;
4797    }
4798#endif /* !defined(NO_CGI) || defined(USE_LUA) || defined(USE_DUKTAPE) */
4799    *is_found = 1;
4800    return;
4801  }
4802
4803  /* If we can't find the actual file, look for the file
4804   * with the same name but a .gz extension. If we find it,
4805   * use that and set the gzipped flag in the file struct
4806   * to indicate that the response need to have the content-
4807   * encoding: gzip header.
4808   * We can only do this if the browser declares support. */
4809  if ((accept_encoding = mg_get_header(conn, "Accept-Encoding")) != NULL) {
4810    if (strstr(accept_encoding, "gzip") != NULL) {
4811      mg_snprintf(
4812          conn, &truncated, gz_path, sizeof(gz_path), "%s.gz", filename);
4813
4814      if (truncated) {
4815        goto interpret_cleanup;
4816      }
4817
4818      if (mg_stat(conn, gz_path, filep)) {
4819        if (filep) {
4820          filep->gzipped = 1;
4821          *is_found = 1;
4822        }
4823        /* Currently gz files can not be scripts. */
4824        return;
4825      }
4826    }
4827  }
4828
4829#if !defined(NO_CGI) || defined(USE_LUA) || defined(USE_DUKTAPE)
4830  /* Support PATH_INFO for CGI scripts. */
4831  for (p = filename + strlen(filename); p > filename + 1; p--) {
4832    if (*p == '/') {
4833      *p = '\0';
4834      if ((0
4835#if !defined(NO_CGI)
4836           || match_prefix(conn->ctx->config[CGI_EXTENSIONS],
4837                           strlen(conn->ctx->config[CGI_EXTENSIONS]),
4838                           filename) > 0
4839#endif
4840#if defined(USE_LUA)
4841           || match_prefix(conn->ctx->config[LUA_SCRIPT_EXTENSIONS],
4842                           strlen(
4843                               conn->ctx->config[LUA_SCRIPT_EXTENSIONS]),
4844                           filename) > 0
4845#endif
4846#if defined(USE_DUKTAPE)
4847           || match_prefix(
4848                  conn->ctx->config[DUKTAPE_SCRIPT_EXTENSIONS],
4849                  strlen(conn->ctx->config[DUKTAPE_SCRIPT_EXTENSIONS]),
4850                  filename) > 0
4851#endif
4852           ) && mg_stat(conn, filename, filep)) {
4853        /* Shift PATH_INFO block one character right, e.g.
4854         * "/x.cgi/foo/bar\x00" => "/x.cgi\x00/foo/bar\x00"
4855         * conn->path_info is pointing to the local variable "path"
4856         * declared in handle_request(), so PATH_INFO is not valid
4857         * after handle_request returns. */
4858        conn->path_info = p + 1;
4859        memmove(p + 2, p + 1, strlen(p + 1) + 1); /* +1 is for
4860                                                   * trailing \0 */
4861        p[1] = '/';
4862        *is_script_resource = 1;
4863        break;
4864      } else {
4865        *p = '/';
4866      }
4867    }
4868  }
4869#endif /* !defined(NO_CGI) || defined(USE_LUA) || defined(USE_DUKTAPE) */
4870#endif /* !defined(NO_FILES) */
4871  return;
4872
4873#if !defined(NO_FILES)
4874/* Reset all outputs */
4875interpret_cleanup:
4876  memset(filep, 0, sizeof(*filep));
4877  *filename = 0;
4878  *is_found = 0;
4879  *is_script_resource = 0;
4880  *is_websocket_request = 0;
4881  *is_put_or_delete_request = 0;
4882#endif /* !defined(NO_FILES) */
4883}
4884
4885
4886/* Check whether full request is buffered. Return:
4887 * -1  if request is malformed
4888 *  0  if request is not yet fully buffered
4889 * >0  actual request length, including last \r\n\r\n */
4890static int
4891get_request_len(const char *buf, int buflen)
4892{
4893  const char *s, *e;
4894  int len = 0;
4895
4896  for (s = buf, e = s + buflen - 1; len <= 0 && s < e; s++)
4897    /* Control characters are not allowed but >=128 is. */
4898    if (!isprint(*(const unsigned char *)s) && *s != '\r' && *s != '\n'
4899        && *(const unsigned char *)s < 128) {
4900      len = -1;
4901      break; /* [i_a] abort scan as soon as one malformed character is
4902              * found; */
4903      /* don't let subsequent \r\n\r\n win us over anyhow */
4904    } else if (s[0] == '\n' && s[1] == '\n') {
4905      len = (int)(s - buf) + 2;
4906    } else if (s[0] == '\n' && &s[1] < e && s[1] == '\r' && s[2] == '\n') {
4907      len = (int)(s - buf) + 3;
4908    }
4909
4910  return len;
4911}
4912
4913
4914#if !defined(NO_CACHING)
4915/* Convert month to the month number. Return -1 on error, or month number */
4916static int
4917get_month_index(const char *s)
4918{
4919  size_t i;
4920
4921  for (i = 0; i < ARRAY_SIZE(month_names); i++) {
4922    if (!strcmp(s, month_names[i])) {
4923      return (int)i;
4924    }
4925  }
4926
4927  return -1;
4928}
4929
4930
4931/* Parse UTC date-time string, and return the corresponding time_t value. */
4932static time_t
4933parse_date_string(const char *datetime)
4934{
4935  char month_str[32] = {0};
4936  int second, minute, hour, day, month, year;
4937  time_t result = (time_t)0;
4938  struct tm tm;
4939
4940  if ((sscanf(datetime,
4941              "%d/%3s/%d %d:%d:%d",
4942              &day,
4943              month_str,
4944              &year,
4945              &hour,
4946              &minute,
4947              &second) == 6) || (sscanf(datetime,
4948                                        "%d %3s %d %d:%d:%d",
4949                                        &day,
4950                                        month_str,
4951                                        &year,
4952                                        &hour,
4953                                        &minute,
4954                                        &second) == 6)
4955      || (sscanf(datetime,
4956                 "%*3s, %d %3s %d %d:%d:%d",
4957                 &day,
4958                 month_str,
4959                 &year,
4960                 &hour,
4961                 &minute,
4962                 &second) == 6) || (sscanf(datetime,
4963                                           "%d-%3s-%d %d:%d:%d",
4964                                           &day,
4965                                           month_str,
4966                                           &year,
4967                                           &hour,
4968                                           &minute,
4969                                           &second) == 6)) {
4970    month = get_month_index(month_str);
4971    if ((month >= 0) && (year >= 1970)) {
4972      memset(&tm, 0, sizeof(tm));
4973      tm.tm_year = year - 1900;
4974      tm.tm_mon = month;
4975      tm.tm_mday = day;
4976      tm.tm_hour = hour;
4977      tm.tm_min = minute;
4978      tm.tm_sec = second;
4979      result = timegm(&tm);
4980    }
4981  }
4982
4983  return result;
4984}
4985#endif /* !NO_CACHING */
4986
4987
4988/* Protect against directory disclosure attack by removing '..',
4989 * excessive '/' and '\' characters */
4990static void
4991remove_double_dots_and_double_slashes(char *s)
4992{
4993  char *p = s;
4994
4995  while (*s != '\0') {
4996    *p++ = *s++;
4997    if (s[-1] == '/' || s[-1] == '\\') {
4998      /* Skip all following slashes, backslashes and double-dots */
4999      while (s[0] != '\0') {
5000        if (s[0] == '/' || s[0] == '\\') {
5001          s++;
5002        } else if (s[0] == '.' && s[1] == '.') {
5003          s += 2;
5004        } else {
5005          break;
5006        }
5007      }
5008    }
5009  }
5010  *p = '\0';
5011}
5012
5013
5014static const struct {
5015  const char *extension;
5016  size_t ext_len;
5017  const char *mime_type;
5018} builtin_mime_types[] = {
5019    /* IANA registered MIME types (http://www.iana.org/assignments/media-types)
5020     * application types */
5021    {".doc", 4, "application/msword"},
5022    {".eps", 4, "application/postscript"},
5023    {".exe", 4, "application/octet-stream"},
5024    {".js", 3, "application/javascript"},
5025    {".json", 5, "application/json"},
5026    {".pdf", 4, "application/pdf"},
5027    {".ps", 3, "application/postscript"},
5028    {".rtf", 4, "application/rtf"},
5029    {".xhtml", 6, "application/xhtml+xml"},
5030    {".xsl", 4, "application/xml"},
5031    {".xslt", 5, "application/xml"},
5032
5033    /* fonts */
5034    {".ttf", 4, "application/font-sfnt"},
5035    {".cff", 4, "application/font-sfnt"},
5036    {".otf", 4, "application/font-sfnt"},
5037    {".aat", 4, "application/font-sfnt"},
5038    {".sil", 4, "application/font-sfnt"},
5039    {".pfr", 4, "application/font-tdpfr"},
5040    {".woff", 5, "application/font-woff"},
5041
5042    /* audio */
5043    {".mp3", 4, "audio/mpeg"},
5044    {".oga", 4, "audio/ogg"},
5045    {".ogg", 4, "audio/ogg"},
5046
5047    /* image */
5048    {".gif", 4, "image/gif"},
5049    {".ief", 4, "image/ief"},
5050    {".jpeg", 5, "image/jpeg"},
5051    {".jpg", 4, "image/jpeg"},
5052    {".jpm", 4, "image/jpm"},
5053    {".jpx", 4, "image/jpx"},
5054    {".png", 4, "image/png"},
5055    {".svg", 4, "image/svg+xml"},
5056    {".tif", 4, "image/tiff"},
5057    {".tiff", 5, "image/tiff"},
5058
5059    /* model */
5060    {".wrl", 4, "model/vrml"},
5061
5062    /* text */
5063    {".css", 4, "text/css"},
5064    {".csv", 4, "text/csv"},
5065    {".htm", 4, "text/html"},
5066    {".html", 5, "text/html"},
5067    {".sgm", 4, "text/sgml"},
5068    {".shtm", 5, "text/html"},
5069    {".shtml", 6, "text/html"},
5070    {".txt", 4, "text/plain"},
5071    {".xml", 4, "text/xml"},
5072
5073    /* video */
5074    {".mov", 4, "video/quicktime"},
5075    {".mp4", 4, "video/mp4"},
5076    {".mpeg", 5, "video/mpeg"},
5077    {".mpg", 4, "video/mpeg"},
5078    {".ogv", 4, "video/ogg"},
5079    {".qt", 3, "video/quicktime"},
5080
5081    /* not registered types
5082     * (http://reference.sitepoint.com/html/mime-types-full,
5083     * http://www.hansenb.pdx.edu/DMKB/dict/tutorials/mime_typ.php, ..) */
5084    {".arj", 4, "application/x-arj-compressed"},
5085    {".gz", 3, "application/x-gunzip"},
5086    {".rar", 4, "application/x-arj-compressed"},
5087    {".swf", 4, "application/x-shockwave-flash"},
5088    {".tar", 4, "application/x-tar"},
5089    {".tgz", 4, "application/x-tar-gz"},
5090    {".torrent", 8, "application/x-bittorrent"},
5091    {".ppt", 4, "application/x-mspowerpoint"},
5092    {".xls", 4, "application/x-msexcel"},
5093    {".zip", 4, "application/x-zip-compressed"},
5094    {".aac",
5095     4,
5096     "audio/aac"}, /* http://en.wikipedia.org/wiki/Advanced_Audio_Coding */
5097    {".aif", 4, "audio/x-aif"},
5098    {".m3u", 4, "audio/x-mpegurl"},
5099    {".mid", 4, "audio/x-midi"},
5100    {".ra", 3, "audio/x-pn-realaudio"},
5101    {".ram", 4, "audio/x-pn-realaudio"},
5102    {".wav", 4, "audio/x-wav"},
5103    {".bmp", 4, "image/bmp"},
5104    {".ico", 4, "image/x-icon"},
5105    {".pct", 4, "image/x-pct"},
5106    {".pict", 5, "image/pict"},
5107    {".rgb", 4, "image/x-rgb"},
5108    {".webm", 5, "video/webm"}, /* http://en.wikipedia.org/wiki/WebM */
5109    {".asf", 4, "video/x-ms-asf"},
5110    {".avi", 4, "video/x-msvideo"},
5111    {".m4v", 4, "video/x-m4v"},
5112    {NULL, 0, NULL}};
5113
5114
5115const char *
5116mg_get_builtin_mime_type(const char *path)
5117{
5118  const char *ext;
5119  size_t i, path_len;
5120
5121  path_len = strlen(path);
5122
5123  for (i = 0; builtin_mime_types[i].extension != NULL; i++) {
5124    ext = path + (path_len - builtin_mime_types[i].ext_len);
5125    if (path_len > builtin_mime_types[i].ext_len
5126        && mg_strcasecmp(ext, builtin_mime_types[i].extension) == 0) {
5127      return builtin_mime_types[i].mime_type;
5128    }
5129  }
5130
5131  return "text/plain";
5132}
5133
5134
5135/* Look at the "path" extension and figure what mime type it has.
5136 * Store mime type in the vector. */
5137static void
5138get_mime_type(struct mg_context *ctx, const char *path, struct vec *vec)
5139{
5140  struct vec ext_vec, mime_vec;
5141  const char *list, *ext;
5142  size_t path_len;
5143
5144  path_len = strlen(path);
5145
5146  if (ctx == NULL || vec == NULL) {
5147    return;
5148  }
5149
5150  /* Scan user-defined mime types first, in case user wants to
5151   * override default mime types. */
5152  list = ctx->config[EXTRA_MIME_TYPES];
5153  while ((list = next_option(list, &ext_vec, &mime_vec)) != NULL) {
5154    /* ext now points to the path suffix */
5155    ext = path + path_len - ext_vec.len;
5156    if (mg_strncasecmp(ext, ext_vec.ptr, ext_vec.len) == 0) {
5157      *vec = mime_vec;
5158      return;
5159    }
5160  }
5161
5162  vec->ptr = mg_get_builtin_mime_type(path);
5163  vec->len = strlen(vec->ptr);
5164}
5165
5166
5167/* Stringify binary data. Output buffer must be twice as big as input,
5168 * because each byte takes 2 bytes in string representation */
5169static void
5170bin2str(char *to, const unsigned char *p, size_t len)
5171{
5172  static const char *hex = "0123456789abcdef";
5173
5174  for (; len--; p++) {
5175    *to++ = hex[p[0] >> 4];
5176    *to++ = hex[p[0] & 0x0f];
5177  }
5178  *to = '\0';
5179}
5180
5181
5182/* Return stringified MD5 hash for list of strings. Buffer must be 33 bytes. */
5183char *
5184mg_md5(char buf[33], ...)
5185{
5186  md5_byte_t hash[16];
5187  const char *p;
5188  va_list ap;
5189  md5_state_t ctx;
5190
5191  md5_init(&ctx);
5192
5193  va_start(ap, buf);
5194  while ((p = va_arg(ap, const char *)) != NULL) {
5195    md5_append(&ctx, (const md5_byte_t *)p, strlen(p));
5196  }
5197  va_end(ap);
5198
5199  md5_finish(&ctx, hash);
5200  bin2str(buf, hash, sizeof(hash));
5201  return buf;
5202}
5203
5204
5205/* Check the user's password, return 1 if OK */
5206static int
5207check_password(const char *method,
5208               const char *ha1,
5209               const char *uri,
5210               const char *nonce,
5211               const char *nc,
5212               const char *cnonce,
5213               const char *qop,
5214               const char *response)
5215{
5216  char ha2[32 + 1], expected_response[32 + 1];
5217
5218  /* Some of the parameters may be NULL */
5219  if (method == NULL || nonce == NULL || nc == NULL || cnonce == NULL
5220      || qop == NULL
5221      || response == NULL) {
5222    return 0;
5223  }
5224
5225  /* NOTE(lsm): due to a bug in MSIE, we do not compare the URI */
5226  if (strlen(response) != 32) {
5227    return 0;
5228  }
5229
5230  mg_md5(ha2, method, ":", uri, NULL);
5231  mg_md5(expected_response,
5232         ha1,
5233         ":",
5234         nonce,
5235         ":",
5236         nc,
5237         ":",
5238         cnonce,
5239         ":",
5240         qop,
5241         ":",
5242         ha2,
5243         NULL);
5244
5245  return mg_strcasecmp(response, expected_response) == 0;
5246}
5247
5248
5249/* Use the global passwords file, if specified by auth_gpass option,
5250 * or search for .htpasswd in the requested directory. */
5251static void
5252open_auth_file(struct mg_connection *conn, const char *path, struct file *filep)
5253{
5254  if (conn != NULL && conn->ctx != NULL) {
5255    char name[PATH_MAX];
5256    const char *p, *e, *gpass = conn->ctx->config[GLOBAL_PASSWORDS_FILE];
5257    struct file file = STRUCT_FILE_INITIALIZER;
5258    int truncated;
5259
5260    if (gpass != NULL) {
5261      /* Use global passwords file */
5262      if (!mg_fopen(conn, gpass, "r", filep)) {
5263#ifdef DEBUG
5264        mg_cry(conn, "fopen(%s): %s", gpass, strerror(ERRNO));
5265#endif
5266      }
5267      /* Important: using local struct file to test path for is_directory
5268       * flag. If filep is used, mg_stat() makes it appear as if auth file
5269       * was opened. */
5270    } else if (mg_stat(conn, path, &file) && file.is_directory) {
5271      mg_snprintf(conn,
5272                  &truncated,
5273                  name,
5274                  sizeof(name),
5275                  "%s/%s",
5276                  path,
5277                  PASSWORDS_FILE_NAME);
5278
5279      if (truncated || !mg_fopen(conn, name, "r", filep)) {
5280#ifdef DEBUG
5281        mg_cry(conn, "fopen(%s): %s", name, strerror(ERRNO));
5282#endif
5283      }
5284    } else {
5285      /* Try to find .htpasswd in requested directory. */
5286      for (p = path, e = p + strlen(p) - 1; e > p; e--) {
5287        if (e[0] == '/') {
5288          break;
5289        }
5290      }
5291      mg_snprintf(conn,
5292                  &truncated,
5293                  name,
5294                  sizeof(name),
5295                  "%.*s/%s",
5296                  (int)(e - p),
5297                  p,
5298                  PASSWORDS_FILE_NAME);
5299
5300      if (truncated || !mg_fopen(conn, name, "r", filep)) {
5301#ifdef DEBUG
5302        mg_cry(conn, "fopen(%s): %s", name, strerror(ERRNO));
5303#endif
5304      }
5305    }
5306  }
5307}
5308
5309
5310/* Parsed Authorization header */
5311struct ah {
5312  char *user, *uri, *cnonce, *response, *qop, *nc, *nonce;
5313};
5314
5315
5316/* Return 1 on success. Always initializes the ah structure. */
5317static int
5318parse_auth_header(struct mg_connection *conn,
5319                  char *buf,
5320                  size_t buf_size,
5321                  struct ah *ah)
5322{
5323  char *name, *value, *s;
5324  const char *auth_header;
5325  uint64_t nonce;
5326
5327  if (!ah || !conn) {
5328    return 0;
5329  }
5330
5331  (void)memset(ah, 0, sizeof(*ah));
5332  if ((auth_header = mg_get_header(conn, "Authorization")) == NULL
5333      || mg_strncasecmp(auth_header, "Digest ", 7) != 0) {
5334    return 0;
5335  }
5336
5337  /* Make modifiable copy of the auth header */
5338  (void)mg_strlcpy(buf, auth_header + 7, buf_size);
5339  s = buf;
5340
5341  /* Parse authorization header */
5342  for (;;) {
5343    /* Gobble initial spaces */
5344    while (isspace(*(unsigned char *)s)) {
5345      s++;
5346    }
5347    name = skip_quoted(&s, "=", " ", 0);
5348    /* Value is either quote-delimited, or ends at first comma or space. */
5349    if (s[0] == '\"') {
5350      s++;
5351      value = skip_quoted(&s, "\"", " ", '\\');
5352      if (s[0] == ',') {
5353        s++;
5354      }
5355    } else {
5356      value = skip_quoted(&s, "", " ", 0); /* IE uses commas, FF uses
5357                                              * spaces */
5358    }
5359    if (*name == '\0') {
5360      break;
5361    }
5362
5363    if (!strcmp(name, "username")) {
5364      ah->user = value;
5365    } else if (!strcmp(name, "cnonce")) {
5366      ah->cnonce = value;
5367    } else if (!strcmp(name, "response")) {
5368      ah->response = value;
5369    } else if (!strcmp(name, "uri")) {
5370      ah->uri = value;
5371    } else if (!strcmp(name, "qop")) {
5372      ah->qop = value;
5373    } else if (!strcmp(name, "nc")) {
5374      ah->nc = value;
5375    } else if (!strcmp(name, "nonce")) {
5376      ah->nonce = value;
5377    }
5378  }
5379
5380#ifndef NO_NONCE_CHECK
5381  /* Read the nonce from the response. */
5382  if (ah->nonce == NULL) {
5383    return 0;
5384  }
5385  s = NULL;
5386  nonce = strtoull(ah->nonce, &s, 10);
5387  if ((s == NULL) || (*s != 0)) {
5388    return 0;
5389  }
5390
5391  /* Convert the nonce from the client to a number. */
5392  nonce ^= conn->ctx->auth_nonce_mask;
5393
5394  /* The converted number corresponds to the time the nounce has been
5395   * created. This should not be earlier than the server start. */
5396  /* Server side nonce check is valuable in all situations but one:
5397   * if the server restarts frequently, but the client should not see
5398   * that, so the server should accept nonces from previous starts. */
5399  /* However, the reasonable default is to not accept a nonce from a
5400   * previous start, so if anyone changed the access rights between
5401   * two restarts, a new login is required. */
5402  if (nonce < (uint64_t)conn->ctx->start_time) {
5403    /* nonce is from a previous start of the server and no longer valid
5404     * (replay attack?) */
5405    return 0;
5406  }
5407  /* Check if the nonce is too high, so it has not (yet) been used by the
5408   * server. */
5409  if (nonce >= ((uint64_t)conn->ctx->start_time + conn->ctx->nonce_count)) {
5410    return 0;
5411  }
5412#endif
5413
5414  /* CGI needs it as REMOTE_USER */
5415  if (ah->user != NULL) {
5416    conn->request_info.remote_user = mg_strdup(ah->user);
5417  } else {
5418    return 0;
5419  }
5420
5421  return 1;
5422}
5423
5424
5425static const char *
5426mg_fgets(char *buf, size_t size, struct file *filep, char **p)
5427{
5428  const char *eof;
5429  size_t len;
5430  const char *memend;
5431
5432  if (!filep) {
5433    return NULL;
5434  }
5435
5436  if (filep->membuf != NULL && *p != NULL) {
5437    memend = (const char *)&filep->membuf[filep->size];
5438    /* Search for \n from p till the end of stream */
5439    eof = (char *)memchr(*p, '\n', (size_t)(memend - *p));
5440    if (eof != NULL) {
5441      eof += 1; /* Include \n */
5442    } else {
5443      eof = memend; /* Copy remaining data */
5444    }
5445    len = (size_t)(eof - *p) > size - 1 ? size - 1 : (size_t)(eof - *p);
5446    memcpy(buf, *p, len);
5447    buf[len] = '\0';
5448    *p += len;
5449    return len ? eof : NULL;
5450  } else if (filep->fp != NULL) {
5451    return fgets(buf, (int)size, filep->fp);
5452  } else {
5453    return NULL;
5454  }
5455}
5456
5457struct read_auth_file_struct {
5458  struct mg_connection *conn;
5459  struct ah ah;
5460  char *domain;
5461  char buf[256 + 256 + 40];
5462  char *f_user;
5463  char *f_domain;
5464  char *f_ha1;
5465};
5466
5467
5468static int
5469read_auth_file(struct file *filep, struct read_auth_file_struct *workdata)
5470{
5471  char *p;
5472  int is_authorized = 0;
5473  struct file fp;
5474  size_t l;
5475
5476  if (!filep || !workdata) {
5477    return 0;
5478  }
5479
5480  /* Loop over passwords file */
5481  p = (char *)filep->membuf;
5482  while (mg_fgets(workdata->buf, sizeof(workdata->buf), filep, &p) != NULL) {
5483    l = strlen(workdata->buf);
5484    while (l > 0) {
5485      if (isspace(workdata->buf[l - 1])
5486          || iscntrl(workdata->buf[l - 1])) {
5487        l--;
5488        workdata->buf[l] = 0;
5489      } else
5490        break;
5491    }
5492    if (l < 1) {
5493      continue;
5494    }
5495
5496    workdata->f_user = workdata->buf;
5497
5498    if (workdata->f_user[0] == ':') {
5499      /* user names may not contain a ':' and may not be empty,
5500       * so lines starting with ':' may be used for a special purpose */
5501      if (workdata->f_user[1] == '#') {
5502        /* :# is a comment */
5503        continue;
5504      } else if (!strncmp(workdata->f_user + 1, "include=", 8)) {
5505        if (mg_fopen(workdata->conn, workdata->f_user + 9, "r", &fp)) {
5506          is_authorized = read_auth_file(&fp, workdata);
5507          mg_fclose(&fp);
5508        } else {
5509          mg_cry(workdata->conn,
5510                 "%s: cannot open authorization file: %s",
5511                 __func__,
5512                 workdata->buf);
5513        }
5514        continue;
5515      }
5516      /* everything is invalid for the moment (might change in the
5517       * future) */
5518      mg_cry(workdata->conn,
5519             "%s: syntax error in authorization file: %s",
5520             __func__,
5521             workdata->buf);
5522      continue;
5523    }
5524
5525    workdata->f_domain = strchr(workdata->f_user, ':');
5526    if (workdata->f_domain == NULL) {
5527      mg_cry(workdata->conn,
5528             "%s: syntax error in authorization file: %s",
5529             __func__,
5530             workdata->buf);
5531      continue;
5532    }
5533    *(workdata->f_domain) = 0;
5534    (workdata->f_domain)++;
5535
5536    workdata->f_ha1 = strchr(workdata->f_domain, ':');
5537    if (workdata->f_ha1 == NULL) {
5538      mg_cry(workdata->conn,
5539             "%s: syntax error in authorization file: %s",
5540             __func__,
5541             workdata->buf);
5542      continue;
5543    }
5544    *(workdata->f_ha1) = 0;
5545    (workdata->f_ha1)++;
5546
5547    if (!strcmp(workdata->ah.user, workdata->f_user)
5548        && !strcmp(workdata->domain, workdata->f_domain)) {
5549      return check_password(workdata->conn->request_info.request_method,
5550                            workdata->f_ha1,
5551                            workdata->ah.uri,
5552                            workdata->ah.nonce,
5553                            workdata->ah.nc,
5554                            workdata->ah.cnonce,
5555                            workdata->ah.qop,
5556                            workdata->ah.response);
5557    }
5558  }
5559
5560  return is_authorized;
5561}
5562
5563
5564/* Authorize against the opened passwords file. Return 1 if authorized. */
5565static int
5566authorize(struct mg_connection *conn, struct file *filep)
5567{
5568  struct read_auth_file_struct workdata;
5569  char buf[MG_BUF_LEN];
5570
5571  if (!conn || !conn->ctx) {
5572    return 0;
5573  }
5574
5575  memset(&workdata, 0, sizeof(workdata));
5576  workdata.conn = conn;
5577
5578  if (!parse_auth_header(conn, buf, sizeof(buf), &workdata.ah)) {
5579    return 0;
5580  }
5581  workdata.domain = conn->ctx->config[AUTHENTICATION_DOMAIN];
5582
5583  return read_auth_file(filep, &workdata);
5584}
5585
5586
5587/* Return 1 if request is authorised, 0 otherwise. */
5588static int
5589check_authorization(struct mg_connection *conn, const char *path)
5590{
5591  char fname[PATH_MAX];
5592  struct vec uri_vec, filename_vec;
5593  const char *list;
5594  struct file file = STRUCT_FILE_INITIALIZER;
5595  int authorized = 1, truncated;
5596
5597  if (!conn || !conn->ctx) {
5598    return 0;
5599  }
5600
5601  list = conn->ctx->config[PROTECT_URI];
5602  while ((list = next_option(list, &uri_vec, &filename_vec)) != NULL) {
5603    if (!memcmp(conn->request_info.local_uri, uri_vec.ptr, uri_vec.len)) {
5604      mg_snprintf(conn,
5605                  &truncated,
5606                  fname,
5607                  sizeof(fname),
5608                  "%.*s",
5609                  (int)filename_vec.len,
5610                  filename_vec.ptr);
5611
5612      if (truncated || !mg_fopen(conn, fname, "r", &file)) {
5613        mg_cry(conn,
5614               "%s: cannot open %s: %s",
5615               __func__,
5616               fname,
5617               strerror(errno));
5618      }
5619      break;
5620    }
5621  }
5622
5623  if (!is_file_opened(&file)) {
5624    open_auth_file(conn, path, &file);
5625  }
5626
5627  if (is_file_opened(&file)) {
5628    authorized = authorize(conn, &file);
5629    mg_fclose(&file);
5630  }
5631
5632  return authorized;
5633}
5634
5635
5636static void
5637send_authorization_request(struct mg_connection *conn)
5638{
5639  char date[64];
5640  time_t curtime = time(NULL);
5641
5642  if (conn && conn->ctx) {
5643    uint64_t nonce = (uint64_t)(conn->ctx->start_time);
5644
5645    (void)pthread_mutex_lock(&conn->ctx->nonce_mutex);
5646    nonce += conn->ctx->nonce_count;
5647    ++conn->ctx->nonce_count;
5648    (void)pthread_mutex_unlock(&conn->ctx->nonce_mutex);
5649
5650    nonce ^= conn->ctx->auth_nonce_mask;
5651    conn->status_code = 401;
5652    conn->must_close = 1;
5653
5654    gmt_time_string(date, sizeof(date), &curtime);
5655
5656    mg_printf(conn, "HTTP/1.1 401 Unauthorized\r\n");
5657    send_no_cache_header(conn);
5658    mg_printf(conn,
5659              "Date: %s\r\n"
5660              "Connection: %s\r\n"
5661              "Content-Length: 0\r\n"
5662              "WWW-Authenticate: Digest qop=\"auth\", realm=\"%s\""
5663              "nonce=\"%" UINT64_FMT "\"\r\n\r\n",
5664              date,
5665              suggest_connection_header(conn),
5666              conn->ctx->config[AUTHENTICATION_DOMAIN],
5667              nonce);
5668  }
5669}
5670
5671
5672#if !defined(NO_FILES)
5673static int
5674is_authorized_for_put(struct mg_connection *conn)
5675{
5676  if (conn) {
5677    struct file file = STRUCT_FILE_INITIALIZER;
5678    const char *passfile = conn->ctx->config[PUT_DELETE_PASSWORDS_FILE];
5679    int ret = 0;
5680
5681    if (passfile != NULL && mg_fopen(conn, passfile, "r", &file)) {
5682      ret = authorize(conn, &file);
5683      mg_fclose(&file);
5684    }
5685
5686    return ret;
5687  }
5688  return 0;
5689}
5690#endif
5691
5692
5693int
5694mg_modify_passwords_file(const char *fname,
5695                         const char *domain,
5696                         const char *user,
5697                         const char *pass)
5698{
5699  int found, i;
5700  char line[512], u[512] = "", d[512] = "", ha1[33], tmp[PATH_MAX + 8];
5701  FILE *fp, *fp2;
5702
5703  found = 0;
5704  fp = fp2 = NULL;
5705
5706  /* Regard empty password as no password - remove user record. */
5707  if (pass != NULL && pass[0] == '\0') {
5708    pass = NULL;
5709  }
5710
5711  /* Other arguments must not be empty */
5712  if (fname == NULL || domain == NULL || user == NULL) {
5713    return 0;
5714  }
5715
5716  /* Using the given file format, user name and domain must not contain ':'
5717   */
5718  if (strchr(user, ':') != NULL) {
5719    return 0;
5720  }
5721  if (strchr(domain, ':') != NULL) {
5722    return 0;
5723  }
5724
5725  /* Do not allow control characters like newline in user name and domain.
5726   * Do not allow excessively long names either. */
5727  for (i = 0; i < 255 && user[i] != 0; i++) {
5728    if (iscntrl(user[i])) {
5729      return 0;
5730    }
5731  }
5732  if (user[i]) {
5733    return 0;
5734  }
5735  for (i = 0; i < 255 && domain[i] != 0; i++) {
5736    if (iscntrl(domain[i])) {
5737      return 0;
5738    }
5739  }
5740  if (domain[i]) {
5741    return 0;
5742  }
5743
5744  /* The maximum length of the path to the password file is limited */
5745  if ((strlen(fname) + 4) >= PATH_MAX) {
5746    return 0;
5747  }
5748
5749  /* Create a temporary file name. Length has been checked before. */
5750  strcpy(tmp, fname);
5751  strcat(tmp, ".tmp");
5752
5753  /* Create the file if does not exist */
5754  /* Use of fopen here is OK, since fname is only ASCII */
5755  if ((fp = fopen(fname, "a+")) != NULL) {
5756    (void)fclose(fp);
5757  }
5758
5759  /* Open the given file and temporary file */
5760  if ((fp = fopen(fname, "r")) == NULL) {
5761    return 0;
5762  } else if ((fp2 = fopen(tmp, "w+")) == NULL) {
5763    fclose(fp);
5764    return 0;
5765  }
5766
5767  /* Copy the stuff to temporary file */
5768  while (fgets(line, sizeof(line), fp) != NULL) {
5769    if (sscanf(line, "%255[^:]:%255[^:]:%*s", u, d) != 2) {
5770      continue;
5771    }
5772    u[255] = 0;
5773    d[255] = 0;
5774
5775    if (!strcmp(u, user) && !strcmp(d, domain)) {
5776      found++;
5777      if (pass != NULL) {
5778        mg_md5(ha1, user, ":", domain, ":", pass, NULL);
5779        fprintf(fp2, "%s:%s:%s\n", user, domain, ha1);
5780      }
5781    } else {
5782      fprintf(fp2, "%s", line);
5783    }
5784  }
5785
5786  /* If new user, just add it */
5787  if (!found && pass != NULL) {
5788    mg_md5(ha1, user, ":", domain, ":", pass, NULL);
5789    fprintf(fp2, "%s:%s:%s\n", user, domain, ha1);
5790  }
5791
5792  /* Close files */
5793  fclose(fp);
5794  fclose(fp2);
5795
5796  /* Put the temp file in place of real file */
5797  IGNORE_UNUSED_RESULT(remove(fname));
5798  IGNORE_UNUSED_RESULT(rename(tmp, fname));
5799
5800  return 1;
5801}
5802
5803
5804static int
5805is_valid_port(unsigned long port)
5806{
5807  return port < 0xffff;
5808}
5809
5810
5811static int
5812mg_inet_pton(int af, const char *src, void *dst, size_t dstlen)
5813{
5814  struct addrinfo hints, *res, *ressave;
5815  int func_ret = 0;
5816  int gai_ret;
5817
5818  memset(&hints, 0, sizeof(struct addrinfo));
5819  hints.ai_family = af;
5820
5821  gai_ret = getaddrinfo(src, NULL, &hints, &res);
5822  if (gai_ret != 0) {
5823    /* gai_strerror could be used to convert gai_ret to a string */
5824    /* POSIX return values: see
5825     * http://pubs.opengroup.org/onlinepubs/9699919799/functions/freeaddrinfo.html
5826     */
5827    /* Windows return values: see
5828     * https://msdn.microsoft.com/en-us/library/windows/desktop/ms738520%28v=vs.85%29.aspx
5829     */
5830    return 0;
5831  }
5832
5833  ressave = res;
5834
5835  while (res) {
5836    if (dstlen >= res->ai_addrlen) {
5837      memcpy(dst, res->ai_addr, res->ai_addrlen);
5838      func_ret = 1;
5839    }
5840    res = res->ai_next;
5841  }
5842
5843  freeaddrinfo(ressave);
5844  return func_ret;
5845}
5846
5847
5848static int
5849connect_socket(struct mg_context *ctx /* may be NULL */,
5850               const char *host,
5851               int port,
5852               int use_ssl,
5853               char *ebuf,
5854               size_t ebuf_len,
5855               SOCKET *sock /* output: socket, must not be NULL */,
5856               union usa *sa /* output: socket address, must not be NULL  */
5857               )
5858{
5859  int ip_ver = 0;
5860  *sock = INVALID_SOCKET;
5861  memset(sa, 0, sizeof(*sa));
5862
5863  if (ebuf_len > 0) {
5864    *ebuf = 0;
5865  }
5866
5867  if (host == NULL) {
5868    mg_snprintf(NULL,
5869                NULL, /* No truncation check for ebuf */
5870                ebuf,
5871                ebuf_len,
5872                "%s",
5873                "NULL host");
5874    return 0;
5875  }
5876
5877  if (port < 0 || !is_valid_port((unsigned)port)) {
5878    mg_snprintf(NULL,
5879                NULL, /* No truncation check for ebuf */
5880                ebuf,
5881                ebuf_len,
5882                "%s",
5883                "invalid port");
5884    return 0;
5885  }
5886
5887  if (use_ssl && (SSLv23_client_method == NULL)) {
5888    mg_snprintf(NULL,
5889                NULL, /* No truncation check for ebuf */
5890                ebuf,
5891                ebuf_len,
5892                "%s",
5893                "SSL is not initialized");
5894    return 0;
5895  }
5896
5897  if (mg_inet_pton(AF_INET, host, &sa->sin, sizeof(sa->sin))) {
5898    sa->sin.sin_port = htons((uint16_t)port);
5899    ip_ver = 4;
5900#ifdef USE_IPV6
5901  } else if (mg_inet_pton(AF_INET6, host, &sa->sin6, sizeof(sa->sin6))) {
5902    sa->sin6.sin6_port = htons((uint16_t)port);
5903    ip_ver = 6;
5904  } else if (host[0] == '[') {
5905    /* While getaddrinfo on Windows will work with [::1],
5906     * getaddrinfo on Linux only works with ::1 (without []). */
5907    size_t l = strlen(host + 1);
5908    char *h = l > 1 ? mg_strdup(host + 1) : NULL;
5909    if (h) {
5910      h[l - 1] = 0;
5911      if (mg_inet_pton(AF_INET6, h, &sa->sin6, sizeof(sa->sin6))) {
5912        sa->sin6.sin6_port = htons((uint16_t)port);
5913        ip_ver = 6;
5914      }
5915      mg_free(h);
5916    }
5917#endif
5918  }
5919
5920  if (ip_ver == 0) {
5921    mg_snprintf(NULL,
5922                NULL, /* No truncation check for ebuf */
5923                ebuf,
5924                ebuf_len,
5925                "%s",
5926                "host not found");
5927    return 0;
5928  }
5929
5930  if (ip_ver == 4) {
5931    *sock = socket(PF_INET, SOCK_STREAM, 0);
5932  }
5933#ifdef USE_IPV6
5934  else if (ip_ver == 6) {
5935    *sock = socket(PF_INET6, SOCK_STREAM, 0);
5936  }
5937#endif
5938
5939  if (*sock == INVALID_SOCKET) {
5940    mg_snprintf(NULL,
5941                NULL, /* No truncation check for ebuf */
5942                ebuf,
5943                ebuf_len,
5944                "socket(): %s",
5945                strerror(ERRNO));
5946    return 0;
5947  }
5948
5949  set_close_on_exec(*sock, fc(ctx));
5950
5951  if ((ip_ver == 4)
5952      && (connect(*sock, (struct sockaddr *)&sa->sin, sizeof(sa->sin))
5953          == 0)) {
5954    /* connected with IPv4 */
5955    return 1;
5956  }
5957
5958#ifdef USE_IPV6
5959  if ((ip_ver == 6)
5960      && (connect(*sock, (struct sockaddr *)&sa->sin6, sizeof(sa->sin6))
5961          == 0)) {
5962    /* connected with IPv6 */
5963    return 1;
5964  }
5965#endif
5966
5967  /* Not connected */
5968  mg_snprintf(NULL,
5969              NULL, /* No truncation check for ebuf */
5970              ebuf,
5971              ebuf_len,
5972              "connect(%s:%d): %s",
5973              host,
5974              port,
5975              strerror(ERRNO));
5976  closesocket(*sock);
5977  *sock = INVALID_SOCKET;
5978  return 0;
5979}
5980
5981
5982int
5983mg_url_encode(const char *src, char *dst, size_t dst_len)
5984{
5985  static const char *dont_escape = "._-$,;~()";
5986  static const char *hex = "0123456789abcdef";
5987  char *pos = dst;
5988  const char *end = dst + dst_len - 1;
5989
5990  for (; *src != '\0' && pos < end; src++, pos++) {
5991    if (isalnum(*(const unsigned char *)src)
5992        || strchr(dont_escape, *(const unsigned char *)src) != NULL) {
5993      *pos = *src;
5994    } else if (pos + 2 < end) {
5995      pos[0] = '%';
5996      pos[1] = hex[(*(const unsigned char *)src) >> 4];
5997      pos[2] = hex[(*(const unsigned char *)src) & 0xf];
5998      pos += 2;
5999    } else {
6000      break;
6001    }
6002  }
6003
6004  *pos = '\0';
6005  return (*src == '\0') ? (int)(pos - dst) : -1;
6006}
6007
6008
6009static void
6010print_dir_entry(struct de *de)
6011{
6012  char size[64], mod[64], href[PATH_MAX];
6013  struct tm *tm;
6014
6015  if (de->file.is_directory) {
6016    mg_snprintf(de->conn,
6017                NULL, /* Buffer is big enough */
6018                size,
6019                sizeof(size),
6020                "%s",
6021                "[DIRECTORY]");
6022  } else {
6023    /* We use (signed) cast below because MSVC 6 compiler cannot
6024     * convert unsigned __int64 to double. Sigh. */
6025    if (de->file.size < 1024) {
6026      mg_snprintf(de->conn,
6027                  NULL, /* Buffer is big enough */
6028                  size,
6029                  sizeof(size),
6030                  "%d",
6031                  (int)de->file.size);
6032    } else if (de->file.size < 0x100000) {
6033      mg_snprintf(de->conn,
6034                  NULL, /* Buffer is big enough */
6035                  size,
6036                  sizeof(size),
6037                  "%.1fk",
6038                  (double)de->file.size / 1024.0);
6039    } else if (de->file.size < 0x40000000) {
6040      mg_snprintf(de->conn,
6041                  NULL, /* Buffer is big enough */
6042                  size,
6043                  sizeof(size),
6044                  "%.1fM",
6045                  (double)de->file.size / 1048576);
6046    } else {
6047      mg_snprintf(de->conn,
6048                  NULL, /* Buffer is big enough */
6049                  size,
6050                  sizeof(size),
6051                  "%.1fG",
6052                  (double)de->file.size / 1073741824);
6053    }
6054  }
6055
6056  /* Note: mg_snprintf will not cause a buffer overflow above.
6057   * So, string truncation checks are not required here. */
6058
6059  tm = localtime(&de->file.last_modified);
6060  if (tm != NULL) {
6061    strftime(mod, sizeof(mod), "%d-%b-%Y %H:%M", tm);
6062  } else {
6063    mg_strlcpy(mod, "01-Jan-1970 00:00", sizeof(mod));
6064    mod[sizeof(mod) - 1] = '\0';
6065  }
6066  mg_url_encode(de->file_name, href, sizeof(href));
6067  de->conn->num_bytes_sent +=
6068      mg_printf(de->conn,
6069                "<tr><td><a href=\"%s%s%s\">%s%s</a></td>"
6070                "<td>&nbsp;%s</td><td>&nbsp;&nbsp;%s</td></tr>\n",
6071                de->conn->request_info.local_uri,
6072                href,
6073                de->file.is_directory ? "/" : "",
6074                de->file_name,
6075                de->file.is_directory ? "/" : "",
6076                mod,
6077                size);
6078}
6079
6080
6081/* This function is called from send_directory() and used for
6082 * sorting directory entries by size, or name, or modification time.
6083 * On windows, __cdecl specification is needed in case if project is built
6084 * with __stdcall convention. qsort always requires __cdels callback. */
6085static int WINCDECL
6086compare_dir_entries(const void *p1, const void *p2)
6087{
6088  if (p1 && p2) {
6089    const struct de *a = (const struct de *)p1, *b = (const struct de *)p2;
6090    const char *query_string = a->conn->request_info.query_string;
6091    int cmp_result = 0;
6092
6093    if (query_string == NULL) {
6094      query_string = "na";
6095    }
6096
6097    if (a->file.is_directory && !b->file.is_directory) {
6098      return -1; /* Always put directories on top */
6099    } else if (!a->file.is_directory && b->file.is_directory) {
6100      return 1; /* Always put directories on top */
6101    } else if (*query_string == 'n') {
6102      cmp_result = strcmp(a->file_name, b->file_name);
6103    } else if (*query_string == 's') {
6104      cmp_result = a->file.size == b->file.size
6105                       ? 0
6106                       : a->file.size > b->file.size ? 1 : -1;
6107    } else if (*query_string == 'd') {
6108      cmp_result =
6109          (a->file.last_modified == b->file.last_modified)
6110              ? 0
6111              : ((a->file.last_modified > b->file.last_modified) ? 1
6112                                                                 : -1);
6113    }
6114
6115    return query_string[1] == 'd' ? -cmp_result : cmp_result;
6116  }
6117  return 0;
6118}
6119
6120
6121static int
6122must_hide_file(struct mg_connection *conn, const char *path)
6123{
6124  if (conn && conn->ctx) {
6125    const char *pw_pattern = "**" PASSWORDS_FILE_NAME "$";
6126    const char *pattern = conn->ctx->config[HIDE_FILES];
6127    return match_prefix(pw_pattern, strlen(pw_pattern), path) > 0
6128           || (pattern != NULL
6129               && match_prefix(pattern, strlen(pattern), path) > 0);
6130  }
6131  return 0;
6132}
6133
6134
6135static int
6136scan_directory(struct mg_connection *conn,
6137               const char *dir,
6138               void *data,
6139               void (*cb)(struct de *, void *))
6140{
6141  char path[PATH_MAX];
6142  struct dirent *dp;
6143  DIR *dirp;
6144  struct de de;
6145  int truncated;
6146
6147  if ((dirp = mg_opendir(conn, dir)) == NULL) {
6148    return 0;
6149  } else {
6150    de.conn = conn;
6151
6152    while ((dp = mg_readdir(dirp)) != NULL) {
6153      /* Do not show current dir and hidden files */
6154      if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, "..")
6155          || must_hide_file(conn, dp->d_name)) {
6156        continue;
6157      }
6158
6159      mg_snprintf(
6160          conn, &truncated, path, sizeof(path), "%s/%s", dir, dp->d_name);
6161
6162      /* If we don't memset stat structure to zero, mtime will have
6163       * garbage and strftime() will segfault later on in
6164       * print_dir_entry(). memset is required only if mg_stat()
6165       * fails. For more details, see
6166       * http://code.google.com/p/mongoose/issues/detail?id=79 */
6167      memset(&de.file, 0, sizeof(de.file));
6168
6169      if (truncated) {
6170        /* If the path is not complete, skip processing. */
6171        continue;
6172      }
6173
6174      if (!mg_stat(conn, path, &de.file)) {
6175        mg_cry(conn,
6176               "%s: mg_stat(%s) failed: %s",
6177               __func__,
6178               path,
6179               strerror(ERRNO));
6180      }
6181      de.file_name = dp->d_name;
6182      cb(&de, data);
6183    }
6184    (void)mg_closedir(dirp);
6185  }
6186  return 1;
6187}
6188
6189
6190#if !defined(NO_FILES)
6191static int
6192remove_directory(struct mg_connection *conn, const char *dir)
6193{
6194  char path[PATH_MAX];
6195  struct dirent *dp;
6196  DIR *dirp;
6197  struct de de;
6198  int truncated;
6199  int ok = 1;
6200
6201  if ((dirp = mg_opendir(conn, dir)) == NULL) {
6202    return 0;
6203  } else {
6204    de.conn = conn;
6205
6206    while ((dp = mg_readdir(dirp)) != NULL) {
6207      /* Do not show current dir (but show hidden files as they will
6208       * also be removed) */
6209      if (!strcmp(dp->d_name, ".") || !strcmp(dp->d_name, "..")) {
6210        continue;
6211      }
6212
6213      mg_snprintf(
6214          conn, &truncated, path, sizeof(path), "%s/%s", dir, dp->d_name);
6215
6216      /* If we don't memset stat structure to zero, mtime will have
6217       * garbage and strftime() will segfault later on in
6218       * print_dir_entry(). memset is required only if mg_stat()
6219       * fails. For more details, see
6220       * http://code.google.com/p/mongoose/issues/detail?id=79 */
6221      memset(&de.file, 0, sizeof(de.file));
6222
6223      if (truncated) {
6224        /* Do not delete anything shorter */
6225        ok = 0;
6226        continue;
6227      }
6228
6229      if (!mg_stat(conn, path, &de.file)) {
6230        mg_cry(conn,
6231               "%s: mg_stat(%s) failed: %s",
6232               __func__,
6233               path,
6234               strerror(ERRNO));
6235        ok = 0;
6236      }
6237      if (de.file.membuf == NULL) {
6238        /* file is not in memory */
6239        if (de.file.is_directory) {
6240          if (remove_directory(conn, path) == 0) {
6241            ok = 0;
6242          }
6243        } else {
6244          if (mg_remove(conn, path) == 0) {
6245            ok = 0;
6246          }
6247        }
6248      } else {
6249        /* file is in memory. It can not be deleted. */
6250        ok = 0;
6251      }
6252    }
6253    (void)mg_closedir(dirp);
6254
6255    IGNORE_UNUSED_RESULT(rmdir(dir));
6256  }
6257
6258  return ok;
6259}
6260#endif
6261
6262
6263struct dir_scan_data {
6264  struct de *entries;
6265  unsigned int num_entries;
6266  unsigned int arr_size;
6267};
6268
6269
6270/* Behaves like realloc(), but frees original pointer on failure */
6271static void *
6272realloc2(void *ptr, size_t size)
6273{
6274  void *new_ptr = mg_realloc(ptr, size);
6275  if (new_ptr == NULL) {
6276    mg_free(ptr);
6277  }
6278  return new_ptr;
6279}
6280
6281
6282static void
6283dir_scan_callback(struct de *de, void *data)
6284{
6285  struct dir_scan_data *dsd = (struct dir_scan_data *)data;
6286
6287  if (dsd->entries == NULL || dsd->num_entries >= dsd->arr_size) {
6288    dsd->arr_size *= 2;
6289    dsd->entries =
6290        (struct de *)realloc2(dsd->entries,
6291                              dsd->arr_size * sizeof(dsd->entries[0]));
6292  }
6293  if (dsd->entries == NULL) {
6294    /* TODO(lsm, low): propagate an error to the caller */
6295    dsd->num_entries = 0;
6296  } else {
6297    dsd->entries[dsd->num_entries].file_name = mg_strdup(de->file_name);
6298    dsd->entries[dsd->num_entries].file = de->file;
6299    dsd->entries[dsd->num_entries].conn = de->conn;
6300    dsd->num_entries++;
6301  }
6302}
6303
6304
6305static void
6306handle_directory_request(struct mg_connection *conn, const char *dir)
6307{
6308  unsigned int i;
6309  int sort_direction;
6310  struct dir_scan_data data = {NULL, 0, 128};
6311  char date[64];
6312  time_t curtime = time(NULL);
6313
6314  if (!scan_directory(conn, dir, &data, dir_scan_callback)) {
6315    send_http_error(conn,
6316                    500,
6317                    "Error: Cannot open directory\nopendir(%s): %s",
6318                    dir,
6319                    strerror(ERRNO));
6320    return;
6321  }
6322
6323  gmt_time_string(date, sizeof(date), &curtime);
6324
6325  if (!conn) {
6326    return;
6327  }
6328
6329  sort_direction = conn->request_info.query_string != NULL
6330                           && conn->request_info.query_string[1] == 'd'
6331                       ? 'a'
6332                       : 'd';
6333
6334  conn->must_close = 1;
6335  mg_printf(conn, "HTTP/1.1 200 OK\r\n");
6336  send_static_cache_header(conn);
6337  mg_printf(conn,
6338            "Date: %s\r\n"
6339            "Connection: close\r\n"
6340            "Content-Type: text/html; charset=utf-8\r\n\r\n",
6341            date);
6342
6343  conn->num_bytes_sent +=
6344      mg_printf(conn,
6345                "<html><head><title>Index of %s</title>"
6346                "<style>th {text-align: left;}</style></head>"
6347                "<body><h1>Index of %s</h1><pre><table cellpadding=\"0\">"
6348                "<tr><th><a href=\"?n%c\">Name</a></th>"
6349                "<th><a href=\"?d%c\">Modified</a></th>"
6350                "<th><a href=\"?s%c\">Size</a></th></tr>"
6351                "<tr><td colspan=\"3\"><hr></td></tr>",
6352                conn->request_info.local_uri,
6353                conn->request_info.local_uri,
6354                sort_direction,
6355                sort_direction,
6356                sort_direction);
6357
6358  /* Print first entry - link to a parent directory */
6359  conn->num_bytes_sent +=
6360      mg_printf(conn,
6361                "<tr><td><a href=\"%s%s\">%s</a></td>"
6362                "<td>&nbsp;%s</td><td>&nbsp;&nbsp;%s</td></tr>\n",
6363                conn->request_info.local_uri,
6364                "..",
6365                "Parent directory",
6366                "-",
6367                "-");
6368
6369  /* Sort and print directory entries */
6370  if (data.entries != NULL) {
6371    qsort(data.entries,
6372          (size_t)data.num_entries,
6373          sizeof(data.entries[0]),
6374          compare_dir_entries);
6375    for (i = 0; i < data.num_entries; i++) {
6376      print_dir_entry(&data.entries[i]);
6377      mg_free(data.entries[i].file_name);
6378    }
6379    mg_free(data.entries);
6380  }
6381
6382  conn->num_bytes_sent += mg_printf(conn, "%s", "</table></body></html>");
6383  conn->status_code = 200;
6384}
6385
6386
6387/* Send len bytes from the opened file to the client. */
6388static void
6389send_file_data(struct mg_connection *conn,
6390               struct file *filep,
6391               int64_t offset,
6392               int64_t len)
6393{
6394  char buf[MG_BUF_LEN];
6395  int to_read, num_read, num_written;
6396  int64_t size;
6397
6398  if (!filep || !conn) {
6399    return;
6400  }
6401
6402  /* Sanity check the offset */
6403  size = filep->size > INT64_MAX ? INT64_MAX : (int64_t)(filep->size);
6404  offset = offset < 0 ? 0 : offset > size ? size : offset;
6405
6406  if (
 Recommendations (Experimental)  R1: (len > 0 && filep != NULL && membuf > 0)
R2: (len > 0 && (filep != NULL) && membuf > 0)
R3: (len > 0 && filep->membuf != NULL && filep->size > 0)
R4: (len == 0 && filep != NULL && membuf > 0)
R5: (len->filep > 0 && membuf != NULL && size == 0)
 Score  Issue:  1 unfamiliar pattern(s) detected 
Cost: 16.25, Total Score: 1016.25
Class: complex_2
len
 > 0 && filep->membuf != NULL && size > 0) {
6407    /* file stored in memory */
6408    if (len > size - offset) {
6409      len = size - offset;
6410    }
6411    mg_write(conn, filep->membuf + offset, (size_t)len);
6412  } else if (len > 0 && filep->fp != NULL) {
6413/* file stored on disk */
6414#if defined(__linux__)
6415    /* sendfile is only available for Linux */
6416    if (conn->throttle == 0 && conn->ssl == 0) {
6417      off_t sf_offs = (off_t)offset;
6418      ssize_t sf_sent;
6419      int sf_file = fileno(filep->fp);
6420      int loop_cnt = 0;
6421
6422      do {
6423        /* 2147479552 (0x7FFFF000) is a limit found by experiment on
6424         * 64 bit Linux (2^31 minus one memory page of 4k?). */
6425        size_t sf_tosend =
6426            (size_t)((len < 0x7FFFF000) ? len : 0x7FFFF000);
6427        sf_sent =
6428            sendfile(conn->client.sock, sf_file, &sf_offs, sf_tosend);
6429        if (sf_sent > 0) {
6430          conn->num_bytes_sent += sf_sent;
6431          len -= sf_sent;
6432          offset += sf_sent;
6433        } else if (loop_cnt == 0) {
6434          /* This file can not be sent using sendfile.
6435           * This might be the case for pseudo-files in the
6436           * /sys/ and /proc/ file system.
6437           * Use the regular user mode copy code instead. */
6438          break;
6439        } else if (sf_sent == 0) {
6440          /* No error, but 0 bytes sent. May be EOF? */
6441          return;
6442        }
6443        loop_cnt++;
6444
6445      } while ((len > 0) && (sf_sent >= 0));
6446
6447      if (sf_sent > 0) {
6448        return; /* OK */
6449      }
6450
6451      /* sf_sent<0 means error, thus fall back to the classic way */
6452      /* This is always the case, if sf_file is not a "normal" file,
6453       * e.g., for sending data from the output of a CGI process. */
6454      offset = (int64_t)sf_offs;
6455    }
6456#endif
6457    if ((offset > 0) && (fseeko(filep->fp, offset, SEEK_SET) != 0)) {
6458      mg_cry(conn, "%s: fseeko() failed: %s", __func__, strerror(ERRNO));
6459      send_http_error(
6460          conn,
6461          500,
6462          "%s",
6463          "Error: Unable to access file at requested position.");
6464    } else {
6465      while (len > 0) {
6466        /* Calculate how much to read from the file in the buffer */
6467        to_read = sizeof(buf);
6468        if ((int64_t)to_read > len) {
6469          to_read = (int)len;
6470        }
6471
6472        /* Read from file, exit the loop on error */
6473        if ((num_read = (int)fread(buf, 1, (size_t)to_read, filep->fp))
6474            <= 0) {
6475          break;
6476        }
6477
6478        /* Send read bytes to the client, exit the loop on error */
6479        if ((num_written = mg_write(conn, buf, (size_t)num_read))
6480            != num_read) {
6481          break;
6482        }
6483
6484        /* Both read and were successful, adjust counters */
6485        conn->num_bytes_sent += num_written;
6486        len -= num_written;
6487      }
6488    }
6489  }
6490}
6491
6492
6493static int
6494parse_range_header(const char *header, int64_t *a, int64_t *b)
6495{
6496  return sscanf(header, "bytes=%" INT64_FMT "-%" INT64_FMT, a, b);
6497}
6498
6499
6500static void
6501construct_etag(char *buf, size_t buf_len, const struct file *filep)
6502{
6503  if (filep != NULL && buf != NULL) {
6504    mg_snprintf(NULL,
6505                NULL, /* All calls to construct_etag use 64 byte buffer */
6506                buf,
6507                buf_len,
6508                "\"%lx.%" INT64_FMT "\"",
6509                (unsigned long)filep->last_modified,
6510                filep->size);
6511  }
6512}
6513
6514
6515static void
6516fclose_on_exec(struct file *filep, struct mg_connection *conn)
6517{
6518  if (filep != NULL && filep->fp != NULL) {
6519#ifdef _WIN32
6520    (void)conn; /* Unused. */
6521#else
6522    if (fcntl(fileno(filep->fp), F_SETFD, FD_CLOEXEC) != 0) {
6523      mg_cry(conn,
6524             "%s: fcntl(F_SETFD FD_CLOEXEC) failed: %s",
6525             __func__,
6526             strerror(ERRNO));
6527    }
6528#endif
6529  }
6530}
6531
6532
6533static void
6534handle_static_file_request(struct mg_connection *conn,
6535                           const char *path,
6536                           struct file *filep,
6537                           const char *mime_type)
6538{
6539  char date[64], lm[64], etag[64];
6540  char range[128]; /* large enough, so there will be no overflow */
6541  const char *msg = "OK", *hdr;
6542  time_t curtime = time(NULL);
6543  int64_t cl, r1, r2;
6544  struct vec mime_vec;
6545  int n, truncated;
6546  char gz_path[PATH_MAX];
6547  const char *encoding = "";
6548  const char *cors1, *cors2, *cors3;
6549
6550  if (conn == NULL || conn->ctx == NULL || filep == NULL) {
6551    return;
6552  }
6553
6554  if (mime_type == NULL) {
6555    get_mime_type(conn->ctx, path, &mime_vec);
6556  } else {
6557    mime_vec.ptr = mime_type;
6558    mime_vec.len = strlen(mime_type);
6559  }
6560  if (filep->size > INT64_MAX) {
6561    send_http_error(conn,
6562                    500,
6563                    "Error: File size is too large to send\n%" INT64_FMT,
6564                    filep->size);
6565  }
6566  cl = (int64_t)filep->size;
6567  conn->status_code = 200;
6568  range[0] = '\0';
6569
6570  /* if this file is in fact a pre-gzipped file, rewrite its filename
6571   * it's important to rewrite the filename after resolving
6572   * the mime type from it, to preserve the actual file's type */
6573  if (filep->gzipped) {
6574    mg_snprintf(conn, &truncated, gz_path, sizeof(gz_path), "%s.gz", path);
6575
6576    if (truncated) {
6577      send_http_error(conn,
6578                      500,
6579                      "Error: Path of zipped file too long (%s)",
6580                      path);
6581      return;
6582    }
6583
6584    path = gz_path;
6585    encoding = "Content-Encoding: gzip\r\n";
6586  }
6587
6588  if (!mg_fopen(conn, path, "rb", filep)) {
6589    send_http_error(conn,
6590                    500,
6591                    "Error: Cannot open file\nfopen(%s): %s",
6592                    path,
6593                    strerror(ERRNO));
6594    return;
6595  }
6596
6597  fclose_on_exec(filep, conn);
6598
6599  /* If Range: header specified, act accordingly */
6600  r1 = r2 = 0;
6601  hdr = mg_get_header(conn, "Range");
6602  if (hdr != NULL && (n = parse_range_header(hdr, &r1, &r2)) > 0 && r1 >= 0
6603      && r2 >= 0) {
6604    /* actually, range requests don't play well with a pre-gzipped
6605     * file (since the range is specified in the uncompressed space) */
6606    if (filep->gzipped) {
6607      send_http_error(
6608          conn,
6609          501,
6610          "%s",
6611          "Error: Range requests in gzipped files are not supported");
6612      mg_fclose(filep);
6613      return;
6614    }
6615    conn->status_code = 206;
6616    cl = n == 2 ? (r2 > cl ? cl : r2) - r1 + 1 : cl - r1;
6617    mg_snprintf(conn,
6618                NULL, /* range buffer is big enough */
6619                range,
6620                sizeof(range),
6621                "Content-Range: bytes "
6622                "%" INT64_FMT "-%" INT64_FMT "/%" INT64_FMT "\r\n",
6623                r1,
6624                r1 + cl - 1,
6625                filep->size);
6626    msg = "Partial Content";
6627  }
6628
6629  hdr = mg_get_header(conn, "Origin");
6630  if (hdr) {
6631    /* Cross-origin resource sharing (CORS), see
6632     * http://www.html5rocks.com/en/tutorials/cors/,
6633     * http://www.html5rocks.com/static/images/cors_server_flowchart.png -
6634     * preflight is not supported for files. */
6635    cors1 = "Access-Control-Allow-Origin: ";
6636    cors2 = conn->ctx->config[ACCESS_CONTROL_ALLOW_ORIGIN];
6637    cors3 = "\r\n";
6638  } else {
6639    cors1 = cors2 = cors3 = "";
6640  }
6641
6642  /* Prepare Etag, Date, Last-Modified headers. Must be in UTC, according to
6643   * http://www.w3.org/Protocols/rfc2616/rfc2616-sec3.html#sec3.3 */
6644  gmt_time_string(date, sizeof(date), &curtime);
6645  gmt_time_string(lm, sizeof(lm), &filep->last_modified);
6646  construct_etag(etag, sizeof(etag), filep);
6647
6648  (void)mg_printf(conn,
6649                  "HTTP/1.1 %d %s\r\n"
6650                  "%s%s%s"
6651                  "Date: %s\r\n",
6652                  conn->status_code,
6653                  msg,
6654                  cors1,
6655                  cors2,
6656                  cors3,
6657                  date);
6658  send_static_cache_header(conn);
6659  (void)mg_printf(conn,
6660                  "Last-Modified: %s\r\n"
6661                  "Etag: %s\r\n"
6662                  "Content-Type: %.*s\r\n"
6663                  "Content-Length: %" INT64_FMT "\r\n"
6664                  "Connection: %s\r\n"
6665                  "Accept-Ranges: bytes\r\n"
6666                  "%s%s\r\n",
6667                  lm,
6668                  etag,
6669                  (int)mime_vec.len,
6670                  mime_vec.ptr,
6671                  cl,
6672                  suggest_connection_header(conn),
6673                  range,
6674                  encoding);
6675
6676  if (strcmp(conn->request_info.request_method, "HEAD") != 0) {
6677    send_file_data(conn, filep, r1, cl);
6678  }
6679  mg_fclose(filep);
6680}
6681
6682
6683void
6684mg_send_file(struct mg_connection *conn, const char *path)
6685{
6686  mg_send_mime_file(conn, path, NULL);
6687}
6688
6689
6690void
6691mg_send_mime_file(struct mg_connection *conn,
6692                  const char *path,
6693                  const char *mime_type)
6694{
6695  struct file file = STRUCT_FILE_INITIALIZER;
6696  if (mg_stat(conn, path, &file)) {
6697    if (file.is_directory) {
6698      if (!conn) {
6699        return;
6700      }
6701      if (!mg_strcasecmp(conn->ctx->config[ENABLE_DIRECTORY_LISTING],
6702                         "yes")) {
6703        handle_directory_request(conn, path);
6704      } else {
6705        send_http_error(conn,
6706                        403,
6707                        "%s",
6708                        "Error: Directory listing denied");
6709      }
6710    } else {
6711      handle_static_file_request(conn, path, &file, mime_type);
6712    }
6713  } else {
6714    send_http_error(conn, 404, "%s", "Error: File not found");
6715  }
6716}
6717
6718
6719/* For a given PUT path, create all intermediate subdirectories.
6720 * Return  0  if the path itself is a directory.
6721 * Return  1  if the path leads to a file.
6722 * Return -1  for if the path is too long.
6723 * Return -2  if path can not be created.
6724*/
6725static int
6726put_dir(struct mg_connection *conn, const char *path)
6727{
6728  char buf[PATH_MAX];
6729  const char *s, *p;
6730  struct file file = STRUCT_FILE_INITIALIZER;
6731  size_t len;
6732  int res = 1;
6733
6734  for (s = p = path + 2; (p = strchr(s, '/')) != NULL; s = ++p) {
6735    len = (size_t)(p - path);
6736    if (len >= sizeof(buf)) {
6737      /* path too long */
6738      res = -1;
6739      break;
6740    }
6741    memcpy(buf, path, len);
6742    buf[len] = '\0';
6743
6744    /* Try to create intermediate directory */
6745    DEBUG_TRACE("mkdir(%s)", buf);
6746    if (!mg_stat(conn, buf, &file) && mg_mkdir(conn, buf, 0755) != 0) {
6747      /* path does not exixt and can not be created */
6748      res = -2;
6749      break;
6750    }
6751
6752    /* Is path itself a directory? */
6753    if (p[1] == '\0') {
6754      res = 0;
6755    }
6756  }
6757
6758  return res;
6759}
6760
6761
6762static void
6763remove_bad_file(const struct mg_connection *conn, const char *path)
6764{
6765  int r = mg_remove(conn, path);
6766  if (r != 0) {
6767    mg_cry(conn, "%s: Cannot remove invalid file %s", __func__, path);
6768  }
6769}
6770
6771
6772long long
6773mg_store_body(struct mg_connection *conn, const char *path)
6774{
6775  char buf[MG_BUF_LEN];
6776  long long len = 0;
6777  int ret, n;
6778  struct file fi;
6779
6780  if (conn->consumed_content != 0) {
6781    mg_cry(conn, "%s: Contents already consumed", __func__);
6782    return -11;
6783  }
6784
6785  ret = put_dir(conn, path);
6786  if (ret < 0) {
6787    /* -1 for path too long,
6788     * -2 for path can not be created. */
6789    return ret;
6790  }
6791  if (ret != 1) {
6792    /* Return 0 means, path itself is a directory. */
6793    return 0;
6794  }
6795
6796  if (mg_fopen(conn, path, "w", &fi) == 0) {
6797    return -12;
6798  }
6799
6800  ret = mg_read(conn, buf, sizeof(buf));
6801  while (ret > 0) {
6802    n = (int)fwrite(buf, 1, (size_t)ret, fi.fp);
6803    if (n != ret) {
6804      mg_fclose(&fi);
6805      remove_bad_file(conn, path);
6806      return -13;
6807    }
6808    ret = mg_read(conn, buf, sizeof(buf));
6809  }
6810
6811  /* TODO: mg_fclose should return an error,
6812   * and every caller should check and handle it. */
6813  if (fclose(fi.fp) != 0) {
6814    remove_bad_file(conn, path);
6815    return -14;
6816  }
6817
6818  return len;
6819}
6820
6821
6822/* Parse HTTP headers from the given buffer, advance buffer to the point
6823 * where parsing stopped. */
6824static void
6825parse_http_headers(char **buf, struct mg_request_info *ri)
6826{
6827  int i;
6828
6829  if (!ri) {
6830    return;
6831  }
6832
6833  ri->num_headers = 0;
6834
6835  for (i = 0; i < (int)ARRAY_SIZE(ri->http_headers); i++) {
6836    char *dp = *buf;
6837    while ((*dp != ':') && (*dp != '\r') && (*dp != 0)) {
6838      dp++;
6839    }
6840    if (!*dp) {
6841      /* neither : nor \r\n. This is not a valid field. */
6842      break;
6843    }
6844    if (*dp == '\r') {
6845      if (dp[1] == '\n') {
6846        /* \r\n */
6847        ri->http_headers[i].name = *buf;
6848        ri->http_headers[i].value = 0;
6849        *buf = dp;
6850      } else {
6851        /* stray \r. This is not valid. */
6852        break;
6853      }
6854    } else {
6855      /* (*dp == ':') */
6856      *dp = 0;
6857      ri->http_headers[i].name = *buf;
6858      do {
6859        dp++;
6860      } while (*dp == ' ');
6861
6862      ri->http_headers[i].value = dp;
6863      *buf = strstr(dp, "\r\n");
6864    }
6865
6866    ri->num_headers = i + 1;
6867    if (*buf) {
6868      (*buf)[0] = 0;
6869      (*buf)[1] = 0;
6870      *buf += 2;
6871    } else {
6872      *buf = dp;
6873      break;
6874    }
6875
6876    if (*buf[0] == '\r') {
6877      /* This is the end of the header */
6878      break;
6879    }
6880  }
6881}
6882
6883
6884static int
6885is_valid_http_method(const char *method)
6886{
6887  return !strcmp(method, "GET")        /* HTTP (RFC 2616) */
6888         || !strcmp(method, "POST")    /* HTTP (RFC 2616) */
6889         || !strcmp(method, "HEAD")    /* HTTP (RFC 2616) */
6890         || !strcmp(method, "PUT")     /* HTTP (RFC 2616) */
6891         || !strcmp(method, "DELETE")  /* HTTP (RFC 2616) */
6892         || !strcmp(method, "OPTIONS") /* HTTP (RFC 2616) */
6893         /* TRACE method (RFC 2616) is not supported for security reasons */
6894         || !strcmp(method, "CONNECT") /* HTTP (RFC 2616) */
6895
6896         || !strcmp(method, "PROPFIND") /* WEBDAV (RFC 2518) */
6897         || !strcmp(method, "MKCOL")    /* WEBDAV (RFC 2518) */
6898
6899         /* Unsupported WEBDAV Methods: */
6900         /* PROPPATCH, COPY, MOVE, LOCK, UNLOCK (RFC 2518) */
6901         /* + 11 methods from RFC 3253 */
6902         /* ORDERPATCH (RFC 3648) */
6903         /* ACL (RFC 3744) */
6904         /* SEARCH (RFC 5323) */
6905         /* + MicroSoft extensions
6906          * https://msdn.microsoft.com/en-us/library/aa142917.aspx */
6907
6908         /* PATCH method only allowed for CGI/Lua/LSP and callbacks. */
6909         || !strcmp(method, "PATCH"); /* PATCH method (RFC 5789) */
6910}
6911
6912
6913/* Parse HTTP request, fill in mg_request_info structure.
6914 * This function modifies the buffer by NUL-terminating
6915 * HTTP request components, header names and header values. */
6916static int
6917parse_http_message(char *buf, int len, struct mg_request_info *ri)
6918{
6919  int is_request, request_length;
6920
6921  if (!ri) {
6922    return 0;
6923  }
6924
6925  request_length = get_request_len(buf, len);
6926
6927  if (request_length > 0) {
6928    /* Reset attributes. DO NOT TOUCH is_ssl, remote_ip, remote_addr,
6929     * remote_port */
6930    ri->remote_user = ri->request_method = ri->request_uri =
6931        ri->http_version = NULL;
6932    ri->num_headers = 0;
6933
6934    buf[request_length - 1] = '\0';
6935
6936    /* RFC says that all initial whitespaces should be ingored */
6937    while (*buf != '\0' && isspace(*(unsigned char *)buf)) {
6938      buf++;
6939    }
6940    ri->request_method = skip(&buf, " ");
6941    ri->request_uri = skip(&buf, " ");
6942    ri->http_version = skip(&buf, "\r\n");
6943
6944    /* HTTP message could be either HTTP request or HTTP response, e.g.
6945     * "GET / HTTP/1.0 ...." or  "HTTP/1.0 200 OK ..." */
6946    is_request = is_valid_http_method(ri->request_method);
6947    if ((is_request && memcmp(ri->http_version, "HTTP/", 5) != 0)
6948        || (!is_request && memcmp(ri->request_method, "HTTP/", 5) != 0)) {
6949      request_length = -1;
6950    } else {
6951      if (is_request) {
6952        ri->http_version += 5;
6953      }
6954      parse_http_headers(&buf, ri);
6955    }
6956  }
6957  return request_length;
6958}
6959
6960
6961/* Keep reading the input (either opened file descriptor fd, or socket sock,
6962 * or SSL descriptor ssl) into buffer buf, until \r\n\r\n appears in the
6963 * buffer (which marks the end of HTTP request). Buffer buf may already
6964 * have some data. The length of the data is stored in nread.
6965 * Upon every read operation, increase nread by the number of bytes read. */
6966static int
6967read_request(FILE *fp,
6968             struct mg_connection *conn,
6969             char *buf,
6970             int bufsiz,
6971             int *nread)
6972{
6973  int request_len, n = 0;
6974  struct timespec last_action_time;
6975  double request_timeout;
6976
6977  if (!conn) {
6978    return 0;
6979  }
6980
6981  memset(&last_action_time, 0, sizeof(last_action_time));
6982
6983  if (conn->ctx->config[REQUEST_TIMEOUT]) {
6984    /* value of request_timeout is in seconds, config in milliseconds */
6985    request_timeout = atof(conn->ctx->config[REQUEST_TIMEOUT]) / 1000.0;
6986  } else {
6987    request_timeout = -1.0;
6988  }
6989
6990  request_len = get_request_len(buf, *nread);
6991
6992  /* first time reading from this connection */
6993  clock_gettime(CLOCK_MONOTONIC, &last_action_time);
6994
6995  while (
6996      (conn->ctx->stop_flag == 0) && (*nread < bufsiz) && (request_len == 0)
6997      && ((mg_difftimespec(&last_action_time, &(conn->req_time))
6998           <= request_timeout) || (request_timeout < 0))
6999      && ((n = pull(fp, conn, buf + *nread, bufsiz - *nread, request_timeout))
7000          > 0)) {
7001    *nread += n;
7002    /* assert(*nread <= bufsiz); */
7003    if (*nread > bufsiz) {
7004      return -2;
7005    }
7006    request_len = get_request_len(buf, *nread);
7007    if (request_timeout > 0.0) {
7008      clock_gettime(CLOCK_MONOTONIC, &last_action_time);
7009    }
7010  }
7011
7012  return (request_len <= 0 && n <= 0) ? -1 : request_len;
7013}
7014
7015#if !defined(NO_FILES)
7016/* For given directory path, substitute it to valid index file.
7017 * Return 1 if index file has been found, 0 if not found.
7018 * If the file is found, it's stats is returned in stp. */
7019static int
7020substitute_index_file(struct mg_connection *conn,
7021                      char *path,
7022                      size_t path_len,
7023                      struct file *filep)
7024{
7025  if (conn && conn->ctx) {
7026    const char *list = conn->ctx->config[INDEX_FILES];
7027    struct file file = STRUCT_FILE_INITIALIZER;
7028    struct vec filename_vec;
7029    size_t n = strlen(path);
7030    int found = 0;
7031
7032    /* The 'path' given to us points to the directory. Remove all trailing
7033     * directory separator characters from the end of the path, and
7034     * then append single directory separator character. */
7035    while (n > 0 && path[n - 1] == '/') {
7036      n--;
7037    }
7038    path[n] = '/';
7039
7040    /* Traverse index files list. For each entry, append it to the given
7041     * path and see if the file exists. If it exists, break the loop */
7042    while ((list = next_option(list, &filename_vec, NULL)) != NULL) {
7043      /* Ignore too long entries that may overflow path buffer */
7044      if (filename_vec.len > path_len - (n + 2)) {
7045        continue;
7046      }
7047
7048      /* Prepare full path to the index file */
7049      mg_strlcpy(path + n + 1, filename_vec.ptr, filename_vec.len + 1);
7050
7051      /* Does it exist? */
7052      if (mg_stat(conn, path, &file)) {
7053        /* Yes it does, break the loop */
7054        *filep = file;
7055        found = 1;
7056        break;
7057      }
7058    }
7059
7060    /* If no index file exists, restore directory path */
7061    if (!found) {
7062      path[n] = '\0';
7063    }
7064
7065    return found;
7066  }
7067  return 0;
7068}
7069#endif
7070
7071
7072#if !defined(NO_CACHING)
7073/* Return True if we should reply 304 Not Modified. */
7074static int
7075is_not_modified(const struct mg_connection *conn, const struct file *filep)
7076{
7077  char etag[64];
7078  const char *ims = mg_get_header(conn, "If-Modified-Since");
7079  const char *inm = mg_get_header(conn, "If-None-Match");
7080  construct_etag(etag, sizeof(etag), filep);
7081  if (!filep) {
7082    return 0;
7083  }
7084  return (inm != NULL && !mg_strcasecmp(etag, inm))
7085         || (ims != NULL && (filep->last_modified <= parse_date_string(ims)));
7086}
7087#endif /* !NO_CACHING */
7088
7089
7090#if !defined(NO_CGI) || !defined(NO_FILES)
7091static int
7092forward_body_data(struct mg_connection *conn, FILE *fp, SOCKET sock, SSL *ssl)
7093{
7094  const char *expect, *body;
7095  char buf[MG_BUF_LEN];
7096  int to_read, nread, success = 0;
7097  int64_t buffered_len;
7098  double timeout = -1.0;
7099
7100  if (!conn) {
7101    return 0;
7102  }
7103  if (conn->ctx->config[REQUEST_TIMEOUT]) {
7104    timeout = atoi(conn->ctx->config[REQUEST_TIMEOUT]) / 1000.0;
7105  }
7106
7107  expect = mg_get_header(conn, "Expect");
7108  /* assert(fp != NULL); */
7109  if (!fp) {
7110    send_http_error(conn, 500, "%s", "Error: NULL File");
7111    return 0;
7112  }
7113
7114  if (conn->content_len == -1 && !conn->is_chunked) {
7115    /* Content length is not specified by the client. */
7116    send_http_error(conn,
7117                    411,
7118                    "%s",
7119                    "Error: Client did not specify content length");
7120  } else if ((expect != NULL)
7121             && (mg_strcasecmp(expect, "100-continue") != 0)) {
7122    /* Client sent an "Expect: xyz" header and xyz is not 100-continue. */
7123    send_http_error(conn,
7124                    417,
7125                    "Error: Can not fulfill expectation %s",
7126                    expect);
7127  } else {
7128    if (expect != NULL) {
7129      (void)mg_printf(conn, "%s", "HTTP/1.1 100 Continue\r\n\r\n");
7130      conn->status_code = 100;
7131    } else {
7132      conn->status_code = 200;
7133    }
7134
7135    buffered_len = (int64_t)(conn->data_len) - (int64_t)conn->request_len
7136                   - conn->consumed_content;
7137
7138    /* assert(buffered_len >= 0); */
7139    /* assert(conn->consumed_content == 0); */
7140
7141    if ((buffered_len < 0) || (conn->consumed_content != 0)) {
7142      send_http_error(conn, 500, "%s", "Error: Size mismatch");
7143      return 0;
7144    }
7145
7146    if (buffered_len > 0) {
7147      if ((int64_t)buffered_len > conn->content_len) {
7148        buffered_len = (int)conn->content_len;
7149      }
7150      body = conn->buf + conn->request_len + conn->consumed_content;
7151      push_all(conn->ctx, fp, sock, ssl, body, (int64_t)buffered_len);
7152      conn->consumed_content += buffered_len;
7153    }
7154
7155    nread = 0;
7156    while (conn->consumed_content < conn->content_len) {
7157      to_read = sizeof(buf);
7158      if ((int64_t)to_read > conn->content_len - conn->consumed_content) {
7159        to_read = (int)(conn->content_len - conn->consumed_content);
7160      }
7161      nread = pull(NULL, conn, buf, to_read, timeout);
7162      if (nread <= 0
7163          || push_all(conn->ctx, fp, sock, ssl, buf, nread) != nread) {
7164        break;
7165      }
7166      conn->consumed_content += nread;
7167    }
7168
7169    if (conn->consumed_content == conn->content_len) {
7170      success = (nread >= 0);
7171    }
7172
7173    /* Each error code path in this function must send an error */
7174    if (!success) {
7175      /* NOTE: Maybe some data has already been sent. */
7176      /* TODO (low): If some data has been sent, a correct error
7177       * reply can no longer be sent, so just close the connection */
7178      send_http_error(conn, 500, "%s", "");
7179    }
7180  }
7181
7182  return success;
7183}
7184#endif
7185
7186#if !defined(NO_CGI)
7187/* This structure helps to create an environment for the spawned CGI program.
7188 * Environment is an array of "VARIABLE=VALUE\0" ASCIIZ strings,
7189 * last element must be NULL.
7190 * However, on Windows there is a requirement that all these VARIABLE=VALUE\0
7191 * strings must reside in a contiguous buffer. The end of the buffer is
7192 * marked by two '\0' characters.
7193 * We satisfy both worlds: we create an envp array (which is vars), all
7194 * entries are actually pointers inside buf. */
7195struct cgi_environment {
7196  struct mg_connection *conn;
7197  /* Data block */
7198  char *buf;      /* Environment buffer */
7199  size_t buflen;  /* Space available in buf */
7200  size_t bufused; /* Space taken in buf */
7201                  /* Index block */
7202  char **var;     /* char **envp */
7203  size_t varlen;  /* Number of variables available in var */
7204  size_t varused; /* Number of variables stored in var */
7205};
7206
7207
7208static void addenv(struct cgi_environment *env,
7209                   PRINTF_FORMAT_STRING(const char *fmt),
7210                   ...) PRINTF_ARGS(2, 3);
7211
7212/* Append VARIABLE=VALUE\0 string to the buffer, and add a respective
7213 * pointer into the vars array. Assumes env != NULL and fmt != NULL. */
7214static void
7215addenv(struct cgi_environment *env, const char *fmt, ...)
7216{
7217  size_t n, space;
7218  int truncated;
7219  char *added;
7220  va_list ap;
7221
7222  /* Calculate how much space is left in the buffer */
7223  space = (env->buflen - env->bufused);
7224
7225  /* Calculate an estimate for the required space */
7226  n = strlen(fmt) + 2 + 128;
7227
7228  do {
7229    if (space <= n) {
7230      /* Allocate new buffer */
7231      n = env->buflen + CGI_ENVIRONMENT_SIZE;
7232      added = (char *)mg_realloc(env->buf, n);
7233      if (!added) {
7234        /* Out of memory */
7235        mg_cry(env->conn,
7236               "%s: Cannot allocate memory for CGI variable [%s]",
7237               __func__,
7238               fmt);
7239        return;
7240      }
7241      env->buf = added;
7242      env->buflen = n;
7243      space = (env->buflen - env->bufused);
7244    }
7245
7246    /* Make a pointer to the free space int the buffer */
7247    added = env->buf + env->bufused;
7248
7249    /* Copy VARIABLE=VALUE\0 string into the free space */
7250    va_start(ap, fmt);
7251    mg_vsnprintf(env->conn, &truncated, added, (size_t)space, fmt, ap);
7252    va_end(ap);
7253
7254    /* Do not add truncated strings to the environment */
7255    if (truncated) {
7256      /* Reallocate the buffer */
7257      space = 0;
7258      n = 1;
7259    }
7260  } while (truncated);
7261
7262  /* Calculate number of bytes added to the environment */
7263  n = strlen(added) + 1;
7264  env->bufused += n;
7265
7266  /* Now update the variable index */
7267  space = (env->varlen - env->varused);
7268  if (space < 2) {
7269    mg_cry(env->conn,
7270           "%s: Cannot register CGI variable [%s]",
7271           __func__,
7272           fmt);
7273    return;
7274  }
7275
7276  /* Append a pointer to the added string into the envp array */
7277  env->var[env->varused] = added;
7278  env->varused++;
7279}
7280
7281
7282static void
7283prepare_cgi_environment(struct mg_connection *conn,
7284                        const char *prog,
7285                        struct cgi_environment *env)
7286{
7287  const char *s;
7288  struct vec var_vec;
7289  char *p, src_addr[IP_ADDR_STR_LEN], http_var_name[128];
7290  int i, truncated;
7291
7292  if (conn == NULL || prog == NULL || env == NULL) {
7293    return;
7294  }
7295
7296  env->conn = conn;
7297  env->buflen = CGI_ENVIRONMENT_SIZE;
7298  env->bufused = 0;
7299  env->buf = (char *)mg_malloc(env->buflen);
7300  env->varlen = MAX_CGI_ENVIR_VARS;
7301  env->varused = 0;
7302  env->var = (char **)mg_malloc(env->buflen * sizeof(char *));
7303
7304  addenv(env, "SERVER_NAME=%s", conn->ctx->config[AUTHENTICATION_DOMAIN]);
7305  addenv(env, "SERVER_ROOT=%s", conn->ctx->config[DOCUMENT_ROOT]);
7306  addenv(env, "DOCUMENT_ROOT=%s", conn->ctx->config[DOCUMENT_ROOT]);
7307  addenv(env, "SERVER_SOFTWARE=%s/%s", "Civetweb", mg_version());
7308
7309  /* Prepare the environment block */
7310  addenv(env, "%s", "GATEWAY_INTERFACE=CGI/1.1");
7311  addenv(env, "%s", "SERVER_PROTOCOL=HTTP/1.1");
7312  addenv(env, "%s", "REDIRECT_STATUS=200"); /* For PHP */
7313
7314#if defined(USE_IPV6)
7315  if (conn->client.lsa.sa.sa_family == AF_INET6) {
7316    addenv(env, "SERVER_PORT=%d", ntohs(conn->client.lsa.sin6.sin6_port));
7317  } else
7318#endif
7319  {
7320    addenv(env, "SERVER_PORT=%d", ntohs(conn->client.lsa.sin.sin_port));
7321  }
7322
7323  sockaddr_to_string(src_addr, sizeof(src_addr), &conn->client.rsa);
7324  addenv(env, "REMOTE_ADDR=%s", src_addr);
7325
7326  addenv(env, "REQUEST_METHOD=%s", conn->request_info.request_method);
7327  addenv(env, "REMOTE_PORT=%d", conn->request_info.remote_port);
7328
7329  addenv(env, "REQUEST_URI=%s", conn->request_info.request_uri);
7330  addenv(env, "LOCAL_URI=%s", conn->request_info.local_uri);
7331
7332  /* SCRIPT_NAME */
7333  addenv(env,
7334         "SCRIPT_NAME=%.*s",
7335         (int)strlen(conn->request_info.local_uri)
7336             - ((conn->path_info == NULL) ? 0 : (int)strlen(conn->path_info)),
7337         conn->request_info.local_uri);
7338
7339  addenv(env, "SCRIPT_FILENAME=%s", prog);
7340  if (conn->path_info == NULL) {
7341    addenv(env, "PATH_TRANSLATED=%s", conn->ctx->config[DOCUMENT_ROOT]);
7342  } else {
7343    addenv(env,
7344           "PATH_TRANSLATED=%s%s",
7345           conn->ctx->config[DOCUMENT_ROOT],
7346           conn->path_info);
7347  }
7348
7349  addenv(env, "HTTPS=%s", conn->ssl == NULL ? "off" : "on");
7350
7351  if ((s = mg_get_header(conn, "Content-Type")) != NULL) {
7352    addenv(env, "CONTENT_TYPE=%s", s);
7353  }
7354  if (conn->request_info.query_string != NULL) {
7355    addenv(env, "QUERY_STRING=%s", conn->request_info.query_string);
7356  }
7357  if ((s = mg_get_header(conn, "Content-Length")) != NULL) {
7358    addenv(env, "CONTENT_LENGTH=%s", s);
7359  }
7360  if ((s = getenv("PATH")) != NULL) {
7361    addenv(env, "PATH=%s", s);
7362  }
7363  if (conn->path_info != NULL) {
7364    addenv(env, "PATH_INFO=%s", conn->path_info);
7365  }
7366
7367  if (conn->status_code > 0) {
7368    /* CGI error handler should show the status code */
7369    addenv(env, "STATUS=%d", conn->status_code);
7370  }
7371
7372#if defined(_WIN32)
7373  if ((s = getenv("COMSPEC")) != NULL) {
7374    addenv(env, "COMSPEC=%s", s);
7375  }
7376  if ((s = getenv("SYSTEMROOT")) != NULL) {
7377    addenv(env, "SYSTEMROOT=%s", s);
7378  }
7379  if ((s = getenv("SystemDrive")) != NULL) {
7380    addenv(env, "SystemDrive=%s", s);
7381  }
7382  if ((s = getenv("ProgramFiles")) != NULL) {
7383    addenv(env, "ProgramFiles=%s", s);
7384  }
7385  if ((s = getenv("ProgramFiles(x86)")) != NULL) {
7386    addenv(env, "ProgramFiles(x86)=%s", s);
7387  }
7388#else
7389  if ((s = getenv("LD_LIBRARY_PATH")) != NULL) {
7390    addenv(env, "LD_LIBRARY_PATH=%s", s);
7391  }
7392#endif /* _WIN32 */
7393
7394  if ((s = getenv("PERLLIB")) != NULL) {
7395    addenv(env, "PERLLIB=%s", s);
7396  }
7397
7398  if (conn->request_info.remote_user != NULL) {
7399    addenv(env, "REMOTE_USER=%s", conn->request_info.remote_user);
7400    addenv(env, "%s", "AUTH_TYPE=Digest");
7401  }
7402
7403  /* Add all headers as HTTP_* variables */
7404  for (i = 0; i < conn->request_info.num_headers; i++) {
7405
7406    (void)mg_snprintf(conn,
7407                      &truncated,
7408                      http_var_name,
7409                      sizeof(http_var_name),
7410                      "HTTP_%s",
7411                      conn->request_info.http_headers[i].name);
7412
7413    if (truncated) {
7414      mg_cry(conn,
7415             "%s: HTTP header variable too long [%s]",
7416             __func__,
7417             conn->request_info.http_headers[i].name);
7418      continue;
7419    }
7420
7421    /* Convert variable name into uppercase, and change - to _ */
7422    for (p = http_var_name; *p != '\0'; p++) {
7423      if (*p == '-') {
7424        *p = '_';
7425      }
7426      *p = (char)toupper(*(unsigned char *)p);
7427    }
7428
7429    addenv(env,
7430           "%s=%s",
7431           http_var_name,
7432           conn->request_info.http_headers[i].value);
7433  }
7434
7435  /* Add user-specified variables */
7436  s = conn->ctx->config[CGI_ENVIRONMENT];
7437  while ((s = next_option(s, &var_vec, NULL)) != NULL) {
7438    addenv(env, "%.*s", (int)var_vec.len, var_vec.ptr);
7439  }
7440
7441  env->var[env->varused] = NULL;
7442  env->buf[env->bufused] = '\0';
7443}
7444
7445
7446static void
7447handle_cgi_request(struct mg_connection *conn, const char *prog)
7448{
7449  char *buf;
7450  size_t buflen;
7451  int headers_len, data_len, i, truncated;
7452  int fdin[2] = {-1, -1}, fdout[2] = {-1, -1}, fderr[2] = {-1, -1};
7453  const char *status, *status_text, *connection_state;
7454  char *pbuf, dir[PATH_MAX], *p;
7455  struct mg_request_info ri;
7456  struct cgi_environment blk;
7457  FILE *in = NULL, *out = NULL, *err = NULL;
7458  struct file fout = STRUCT_FILE_INITIALIZER;
7459  pid_t pid = (pid_t)-1;
7460
7461  if (conn == NULL) {
7462    return;
7463  }
7464
7465  buf = NULL;
7466  buflen = 16384;
7467  prepare_cgi_environment(conn, prog, &blk);
7468
7469  /* CGI must be executed in its own directory. 'dir' must point to the
7470   * directory containing executable program, 'p' must point to the
7471   * executable program name relative to 'dir'. */
7472  (void)mg_snprintf(conn, &truncated, dir, sizeof(dir), "%s", prog);
7473
7474  if (truncated) {
7475    mg_cry(conn, "Error: CGI program \"%s\": Path too long", prog);
7476    send_http_error(conn, 500, "Error: %s", "CGI path too long");
7477    goto done;
7478  }
7479
7480  if ((p = strrchr(dir, '/')) != NULL) {
7481    *p++ = '\0';
7482  } else {
7483    dir[0] = '.', dir[1] = '\0';
7484    p = (char *)prog;
7485  }
7486
7487  if (pipe(fdin) != 0 || pipe(fdout) != 0 || pipe(fderr) != 0) {
7488    status = strerror(ERRNO);
7489    mg_cry(conn,
7490           "Error: CGI program \"%s\": Can not create CGI pipes: %s",
7491           prog,
7492           status);
7493    send_http_error(conn, 500, "Error: Cannot create CGI pipe: %s", status);
7494    goto done;
7495  }
7496
7497  pid = spawn_process(conn, p, blk.buf, blk.var, fdin, fdout, fderr, dir);
7498
7499  if (pid == (pid_t)-1) {
7500    status = strerror(ERRNO);
7501    mg_cry(conn,
7502           "Error: CGI program \"%s\": Can not spawn CGI process: %s",
7503           prog,
7504           status);
7505    send_http_error(conn,
7506                    500,
7507                    "Error: Cannot spawn CGI process [%s]: %s",
7508                    prog,
7509                    status);
7510    goto done;
7511  }
7512
7513  /* Make sure child closes all pipe descriptors. It must dup them to 0,1 */
7514  set_close_on_exec((SOCKET)fdin[0], conn);  /* stdin read */
7515  set_close_on_exec((SOCKET)fdout[1], conn); /* stdout write */
7516  set_close_on_exec((SOCKET)fderr[1], conn); /* stderr write */
7517  set_close_on_exec((SOCKET)fdin[1], conn);  /* stdin write */
7518  set_close_on_exec((SOCKET)fdout[0], conn); /* stdout read */
7519  set_close_on_exec((SOCKET)fderr[0], conn); /* stderr read */
7520
7521  /* Parent closes only one side of the pipes.
7522   * If we don't mark them as closed, close() attempt before
7523   * return from this function throws an exception on Windows.
7524   * Windows does not like when closed descriptor is closed again. */
7525  (void)close(fdin[0]);
7526  (void)close(fdout[1]);
7527  (void)close(fderr[1]);
7528  fdin[0] = fdout[1] = fderr[1] = -1;
7529
7530  if ((in = fdopen(fdin[1], "wb")) == NULL) {
7531    status = strerror(ERRNO);
7532    mg_cry(conn,
7533           "Error: CGI program \"%s\": Can not open stdin: %s",
7534           prog,
7535           status);
7536    send_http_error(conn,
7537                    500,
7538                    "Error: CGI can not open fdin\nfopen: %s",
7539                    status);
7540    goto done;
7541  }
7542
7543  if ((out = fdopen(fdout[0], "rb")) == NULL) {
7544    status = strerror(ERRNO);
7545    mg_cry(conn,
7546           "Error: CGI program \"%s\": Can not open stdout: %s",
7547           prog,
7548           status);
7549    send_http_error(conn,
7550                    500,
7551                    "Error: CGI can not open fdout\nfopen: %s",
7552                    status);
7553    goto done;
7554  }
7555
7556  if ((err = fdopen(fderr[0], "rb")) == NULL) {
7557    status = strerror(ERRNO);
7558    mg_cry(conn,
7559           "Error: CGI program \"%s\": Can not open stderr: %s",
7560           prog,
7561           status);
7562    send_http_error(conn,
7563                    500,
7564                    "Error: CGI can not open fdout\nfopen: %s",
7565                    status);
7566    goto done;
7567  }
7568
7569  setbuf(in, NULL);
7570  setbuf(out, NULL);
7571  setbuf(err, NULL);
7572  fout.fp = out;
7573
7574  if ((conn->request_info.content_length > 0) || conn->is_chunked) {
7575    /* This is a POST/PUT request, or another request with body data. */
7576    if (!forward_body_data(conn, in, INVALID_SOCKET, NULL)) {
7577      /* Error sending the body data */
7578      mg_cry(conn,
7579             "Error: CGI program \"%s\": Forward body data failed",
7580             prog);
7581      goto done;
7582    }
7583  }
7584
7585  /* Close so child gets an EOF. */
7586  fclose(in);
7587  in = NULL;
7588  fdin[1] = -1;
7589
7590  /* Now read CGI reply into a buffer. We need to set correct
7591   * status code, thus we need to see all HTTP headers first.
7592   * Do not send anything back to client, until we buffer in all
7593   * HTTP headers. */
7594  data_len = 0;
7595  buf = (char *)mg_malloc(buflen);
7596  if (buf == NULL) {
7597    send_http_error(conn,
7598                    500,
7599                    "Error: Not enough memory for CGI buffer (%u bytes)",
7600                    (unsigned int)buflen);
7601    mg_cry(conn,
7602           "Error: CGI program \"%s\": Not enough memory for buffer (%u "
7603           "bytes)",
7604           prog,
7605           (unsigned int)buflen);
7606    goto done;
7607  }
7608  headers_len = read_request(out, conn, buf, (int)buflen, &data_len);
7609  if (headers_len <= 0) {
7610
7611    /* Could not parse the CGI response. Check if some error message on
7612     * stderr. */
7613    i = pull_all(err, conn, buf, (int)buflen);
7614    if (i > 0) {
7615      mg_cry(conn,
7616             "Error: CGI program \"%s\" sent error "
7617             "message: [%.*s]",
7618             prog,
7619             i,
7620             buf);
7621      send_http_error(conn,
7622                      500,
7623                      "Error: CGI program \"%s\" sent error "
7624                      "message: [%.*s]",
7625                      prog,
7626                      i,
7627                      buf);
7628    } else {
7629      mg_cry(conn,
7630             "Error: CGI program sent malformed or too big "
7631             "(>%u bytes) HTTP headers: [%.*s]",
7632             (unsigned)buflen,
7633             data_len,
7634             buf);
7635
7636      send_http_error(conn,
7637                      500,
7638                      "Error: CGI program sent malformed or too big "
7639                      "(>%u bytes) HTTP headers: [%.*s]",
7640                      (unsigned)buflen,
7641                      data_len,
7642                      buf);
7643    }
7644
7645    goto done;
7646  }
7647  pbuf = buf;
7648  buf[headers_len - 1] = '\0';
7649  parse_http_headers(&pbuf, &ri);
7650
7651  /* Make up and send the status line */
7652  status_text = "OK";
7653  if ((status = get_header(&ri, "Status")) != NULL) {
7654    conn->status_code = atoi(status);
7655    status_text = status;
7656    while (isdigit(*(const unsigned char *)status_text)
7657           || *status_text == ' ') {
7658      status_text++;
7659    }
7660  } else if (get_header(&ri, "Location") != NULL) {
7661    conn->status_code = 302;
7662  } else {
7663    conn->status_code = 200;
7664  }
7665  connection_state = get_header(&ri, "Connection");
7666  if (!header_has_option(connection_state, "keep-alive")) {
7667    conn->must_close = 1;
7668  }
7669  (void)mg_printf(conn, "HTTP/1.1 %d %s\r\n", conn->status_code, status_text);
7670
7671  /* Send headers */
7672  for (i = 0; i < ri.num_headers; i++) {
7673    mg_printf(conn,
7674              "%s: %s\r\n",
7675              ri.http_headers[i].name,
7676              ri.http_headers[i].value);
7677  }
7678  mg_write(conn, "\r\n", 2);
7679
7680  /* Send chunk of data that may have been read after the headers */
7681  conn->num_bytes_sent +=
7682      mg_write(conn, buf + headers_len, (size_t)(data_len - headers_len));
7683
7684  /* Read the rest of CGI output and send to the client */
7685  send_file_data(conn, &fout, 0, INT64_MAX);
7686
7687done:
7688  mg_free(blk.var);
7689  mg_free(blk.buf);
7690
7691  if (pid != (pid_t)-1) {
7692    kill(pid, SIGKILL);
7693#if !defined(_WIN32)
7694    {
7695      int st;
7696      while (waitpid(pid, &st, 0) != -1)
7697        ; /* clean zombies */
7698    }
7699#endif
7700  }
7701  if (fdin[0] != -1) {
7702    close(fdin[0]);
7703  }
7704  if (fdout[1] != -1) {
7705    close(fdout[1]);
7706  }
7707
7708  if (in != NULL) {
7709    fclose(in);
7710  } else if (fdin[1] != -1) {
7711    close(fdin[1]);
7712  }
7713
7714  if (out != NULL) {
7715    fclose(out);
7716  } else if (fdout[0] != -1) {
7717    close(fdout[0]);
7718  }
7719
7720  if (err != NULL) {
7721    fclose(err);
7722  } else if (fderr[0] != -1) {
7723    close(fderr[0]);
7724  }
7725
7726  if (buf != NULL) {
7727    mg_free(buf);
7728  }
7729}
7730#endif /* !NO_CGI */
7731
7732
7733#if !defined(NO_FILES)
7734static void
7735mkcol(struct mg_connection *conn, const char *path)
7736{
7737  int rc, body_len;
7738  struct de de;
7739  char date[64];
7740  time_t curtime = time(NULL);
7741
7742  if (conn == NULL) {
7743    return;
7744  }
7745
7746  /* TODO (mid): Check the send_http_error situations in this function */
7747
7748  memset(&de.file, 0, sizeof(de.file));
7749  if (!mg_stat(conn, path, &de.file)) {
7750    mg_cry(conn,
7751           "%s: mg_stat(%s) failed: %s",
7752           __func__,
7753           path,
7754           strerror(ERRNO));
7755  }
7756
7757  if (de.file.last_modified) {
7758    /* TODO (high): This check does not seem to make any sense ! */
7759    send_http_error(
7760        conn, 405, "Error: mkcol(%s): %s", path, strerror(ERRNO));
7761    return;
7762  }
7763
7764  body_len = conn->data_len - conn->request_len;
7765  if (body_len > 0) {
7766    send_http_error(
7767        conn, 415, "Error: mkcol(%s): %s", path, strerror(ERRNO));
7768    return;
7769  }
7770
7771  rc = mg_mkdir(conn, path, 0755);
7772
7773  if (rc == 0) {
7774    conn->status_code = 201;
7775    gmt_time_string(date, sizeof(date), &curtime);
7776    mg_printf(conn,
7777              "HTTP/1.1 %d Created\r\n"
7778              "Date: %s\r\n",
7779              conn->status_code,
7780              date);
7781    send_static_cache_header(conn);
7782    mg_printf(conn,
7783              "Content-Length: 0\r\n"
7784              "Connection: %s\r\n\r\n",
7785              suggest_connection_header(conn));
7786  } else if (rc == -1) {
7787    if (errno == EEXIST) {
7788      send_http_error(
7789          conn, 405, "Error: mkcol(%s): %s", path, strerror(ERRNO));
7790    } else if (errno == EACCES) {
7791      send_http_error(
7792          conn, 403, "Error: mkcol(%s): %s", path, strerror(ERRNO));
7793    } else if (errno == ENOENT) {
7794      send_http_error(
7795          conn, 409, "Error: mkcol(%s): %s", path, strerror(ERRNO));
7796    } else {
7797      send_http_error(conn, 500, "fopen(%s): %s", path, strerror(ERRNO));
7798    }
7799  }
7800}
7801
7802
7803static void
7804put_file(struct mg_connection *conn, const char *path)
7805{
7806  struct file file = STRUCT_FILE_INITIALIZER;
7807  const char *range;
7808  int64_t r1, r2;
7809  int rc;
7810  char date[64];
7811  time_t curtime = time(NULL);
7812
7813  if (conn == NULL) {
7814    return;
7815  }
7816
7817  if (mg_stat(conn, path, &file)) {
7818    /* File already exists */
7819    conn->status_code = 200;
7820
7821    if (file.is_directory) {
7822      /* This is an already existing directory,
7823       * so there is nothing to do for the server. */
7824      rc = 0;
7825
7826    } else {
7827      /* File exists and is not a directory. */
7828      /* Can it be replaced? */
7829
7830      if (file.membuf != NULL) {
7831        /* This is an "in-memory" file, that can not be replaced */
7832        send_http_error(
7833            conn,
7834            405,
7835            "Error: Put not possible\nReplacing %s is not supported",
7836            path);
7837        return;
7838      }
7839
7840      /* Check if the server may write this file */
7841      if (access(path, W_OK) == 0) {
7842        /* Access granted */
7843        conn->status_code = 200;
7844        rc = 1;
7845      } else {
7846        send_http_error(
7847            conn,
7848            403,
7849            "Error: Put not possible\nReplacing %s is not allowed",
7850            path);
7851        return;
7852      }
7853    }
7854  } else {
7855    /* File should be created */
7856    conn->status_code = 201;
7857    rc = put_dir(conn, path);
7858  }
7859
7860  if (rc == 0) {
7861    /* put_dir returns 0 if path is a directory */
7862    gmt_time_string(date, sizeof(date), &curtime);
7863    mg_printf(conn,
7864              "HTTP/1.1 %d %s\r\n",
7865              conn->status_code,
7866              mg_get_response_code_text(NULL, conn->status_code));
7867    send_no_cache_header(conn);
7868    mg_printf(conn,
7869              "Date: %s\r\n"
7870              "Content-Length: 0\r\n"
7871              "Connection: %s\r\n\r\n",
7872              date,
7873              suggest_connection_header(conn));
7874
7875    /* Request to create a directory has been fulfilled successfully.
7876     * No need to put a file. */
7877    return;
7878  }
7879
7880  if (rc == -1) {
7881    /* put_dir returns -1 if the path is too long */
7882    send_http_error(conn,
7883                    414,
7884                    "Error: Path too long\nput_dir(%s): %s",
7885                    path,
7886                    strerror(ERRNO));
7887    return;
7888  }
7889
7890  if (rc == -2) {
7891    /* put_dir returns -2 if the directory can not be created */
7892    send_http_error(conn,
7893                    500,
7894                    "Error: Can not create directory\nput_dir(%s): %s",
7895                    path,
7896                    strerror(ERRNO));
7897    return;
7898  }
7899
7900  /* A file should be created or overwritten. */
7901  if (!mg_fopen(conn, path, "wb+", &file) || file.fp == NULL) {
7902    mg_fclose(&file);
7903    send_http_error(conn,
7904                    500,
7905                    "Error: Can not create file\nfopen(%s): %s",
7906                    path,
7907                    strerror(ERRNO));
7908    return;
7909  }
7910
7911  fclose_on_exec(&file, conn);
7912  range = mg_get_header(conn, "Content-Range");
7913  r1 = r2 = 0;
7914  if (range != NULL && parse_range_header(range, &r1, &r2) > 0) {
7915    conn->status_code = 206; /* Partial content */
7916    fseeko(file.fp, r1, SEEK_SET);
7917  }
7918
7919  if (!forward_body_data(conn, file.fp, INVALID_SOCKET, NULL)) {
7920    /* forward_body_data failed.
7921     * The error code has already been sent to the client,
7922     * and conn->status_code is already set. */
7923    mg_fclose(&file);
7924    return;
7925  }
7926
7927  gmt_time_string(date, sizeof(date), &curtime);
7928  mg_printf(conn,
7929            "HTTP/1.1 %d %s\r\n",
7930            conn->status_code,
7931            mg_get_response_code_text(NULL, conn->status_code));
7932  send_no_cache_header(conn);
7933  mg_printf(conn,
7934            "Date: %s\r\n"
7935            "Content-Length: 0\r\n"
7936            "Connection: %s\r\n\r\n",
7937            date,
7938            suggest_connection_header(conn));
7939
7940  mg_fclose(&file);
7941}
7942
7943
7944static void
7945delete_file(struct mg_connection *conn, const char *path)
7946{
7947  struct de de;
7948  memset(&de.file, 0, sizeof(de.file));
7949  if (!mg_stat(conn, path, &de.file)) {
7950    /* mg_stat returns 0 if the file does not exist */
7951    send_http_error(conn,
7952                    404,
7953                    "Error: Cannot delete file\nFile %s not found",
7954                    path);
7955    return;
7956  }
7957
7958  if (de.file.membuf != NULL) {
7959    /* the file is cached in memory */
7960    send_http_error(
7961        conn,
7962        405,
7963        "Error: Delete not possible\nDeleting %s is not supported",
7964        path);
7965    return;
7966  }
7967
7968  if (de.file.is_directory) {
7969    if (remove_directory(conn, path)) {
7970      /* Delete is successful: Return 204 without content. */
7971      send_http_error(conn, 204, "%s", "");
7972    } else {
7973      /* Delete is not successful: Return 500 (Server error). */
7974      send_http_error(conn, 500, "Error: Could not delete %s", path);
7975    }
7976    return;
7977  }
7978
7979  /* This is an existing file (not a directory).
7980   * Check if write permission is granted. */
7981  if (access(path, W_OK) != 0) {
7982    /* File is read only */
7983    send_http_error(
7984        conn,
7985        403,
7986        "Error: Delete not possible\nDeleting %s is not allowed",
7987        path);
7988    return;
7989  }
7990
7991  /* Try to delete it. */
7992  if (mg_remove(conn, path) == 0) {
7993    /* Delete was successful: Return 204 without content. */
7994    send_http_error(conn, 204, "%s", "");
7995  } else {
7996    /* Delete not successful (file locked). */
7997    send_http_error(conn,
7998                    423,
7999                    "Error: Cannot delete file\nremove(%s): %s",
8000                    path,
8001                    strerror(ERRNO));
8002  }
8003}
8004#endif /* !NO_FILES */
8005
8006
8007static void
8008send_ssi_file(struct mg_connection *, const char *, struct file *, int);
8009
8010
8011static void
8012do_ssi_include(struct mg_connection *conn,
8013               const char *ssi,
8014               char *tag,
8015               int include_level)
8016{
8017  char file_name[MG_BUF_LEN], path[512], *p;
8018  struct file file = STRUCT_FILE_INITIALIZER;
8019  size_t len;
8020  int truncated = 0;
8021
8022  if (conn == NULL) {
8023    return;
8024  }
8025
8026  /* sscanf() is safe here, since send_ssi_file() also uses buffer
8027   * of size MG_BUF_LEN to get the tag. So strlen(tag) is
8028   * always < MG_BUF_LEN. */
8029  if (sscanf(tag, " virtual=\"%511[^\"]\"", file_name) == 1) {
8030    /* File name is relative to the webserver root */
8031    file_name[511] = 0;
8032    (void)mg_snprintf(conn,
8033                      &truncated,
8034                      path,
8035                      sizeof(path),
8036                      "%s/%s",
8037                      conn->ctx->config[DOCUMENT_ROOT],
8038                      file_name);
8039
8040  } else if (sscanf(tag, " abspath=\"%511[^\"]\"", file_name) == 1) {
8041    /* File name is relative to the webserver working directory
8042     * or it is absolute system path */
8043    file_name[511] = 0;
8044    (void)
8045        mg_snprintf(conn, &truncated, path, sizeof(path), "%s", file_name);
8046
8047  } else if (sscanf(tag, " file=\"%511[^\"]\"", file_name) == 1
8048             || sscanf(tag, " \"%511[^\"]\"", file_name) == 1) {
8049    /* File name is relative to the currect document */
8050    file_name[511] = 0;
8051    (void)mg_snprintf(conn, &truncated, path, sizeof(path), "%s", ssi);
8052
8053    if (!truncated) {
8054      if ((p = strrchr(path, '/')) != NULL) {
8055        p[1] = '\0';
8056      }
8057      len = strlen(path);
8058      (void)mg_snprintf(conn,
8059                        &truncated,
8060                        path + len,
8061                        sizeof(path) - len,
8062                        "%s",
8063                        file_name);
8064    }
8065
8066  } else {
8067    mg_cry(conn, "Bad SSI #include: [%s]", tag);
8068    return;
8069  }
8070
8071  if (truncated) {
8072    mg_cry(conn, "SSI #include path length overflow: [%s]", tag);
8073    return;
8074  }
8075
8076  if (!mg_fopen(conn, path, "rb", &file)) {
8077    mg_cry(conn,
8078           "Cannot open SSI #include: [%s]: fopen(%s): %s",
8079           tag,
8080           path,
8081           strerror(ERRNO));
8082  } else {
8083    fclose_on_exec(&file, conn);
8084    if (match_prefix(conn->ctx->config[SSI_EXTENSIONS],
8085                     strlen(conn->ctx->config[SSI_EXTENSIONS]),
8086                     path) > 0) {
8087      send_ssi_file(conn, path, &file, include_level + 1);
8088    } else {
8089      send_file_data(conn, &file, 0, INT64_MAX);
8090    }
8091    mg_fclose(&file);
8092  }
8093}
8094
8095
8096#if !defined(NO_POPEN)
8097static void
8098do_ssi_exec(struct mg_connection *conn, char *tag)
8099{
8100  char cmd[1024] = "";
8101  struct file file = STRUCT_FILE_INITIALIZER;
8102
8103  if (sscanf(tag, " \"%1023[^\"]\"", cmd) != 1) {
8104    mg_cry(conn, "Bad SSI #exec: [%s]", tag);
8105  } else {
8106    cmd[1023] = 0;
8107    if ((file.fp = popen(cmd, "r")) == NULL) {
8108      mg_cry(conn, "Cannot SSI #exec: [%s]: %s", cmd, strerror(ERRNO));
8109    } else {
8110      send_file_data(conn, &file, 0, INT64_MAX);
8111      pclose(file.fp);
8112    }
8113  }
8114}
8115#endif /* !NO_POPEN */
8116
8117
8118static int
8119mg_fgetc(struct file *filep, int offset)
8120{
8121  if (filep == NULL) {
8122    return EOF;
8123  }
8124  if (
 Recommendations (Experimental)  R1: (filep != NULL && membuf >= 0 && membuf < offset)
R2: (filep != NULL && filep->membuf >= 0 && offset)
R3: ((filep != NULL) && (membuf >= 0) && (membuf < offset))
R4: (filep->membuf != NULL && offset >= 0 && offset < filep->unsigned int)
R5: (!(filep == NULL && membuf == 0))
 Score  Issue:  1 unfamiliar pattern(s) detected 
Cost: 19.50, Total Score: 1019.50
Class: complex_2
filep
->membuf != NULL && offset >= 0
8125      && ((unsigned int)(offset)) < filep->size) {
8126    return ((const unsigned char *)filep->membuf)[offset];
8127  } else if (filep->fp != NULL) {
8128    return fgetc(filep->fp);
8129  } else {
8130    return EOF;
8131  }
8132}
8133
8134
8135static void
8136send_ssi_file(struct mg_connection *conn,
8137              const char *path,
8138              struct file *filep,
8139              int include_level)
8140{
8141  char buf[MG_BUF_LEN];
8142  int ch, offset, len, in_ssi_tag;
8143
8144  if (include_level > 10) {
8145    mg_cry(conn, "SSI #include level is too deep (%s)", path);
8146    return;
8147  }
8148
8149  in_ssi_tag = len = offset = 0;
8150  while ((ch = mg_fgetc(filep, offset)) != EOF) {
8151    if (in_ssi_tag && ch == '>') {
8152      in_ssi_tag = 0;
8153      buf[len++] = (char)ch;
8154      buf[len] = '\0';
8155      /* assert(len <= (int) sizeof(buf)); */
8156      if (len > (int)sizeof(buf)) {
8157        break;
8158      }
8159      if (len < 6 || memcmp(buf, "<!--#", 5) != 0) {
8160        /* Not an SSI tag, pass it */
8161        (void)mg_write(conn, buf, (size_t)len);
8162      } else {
8163        if (!memcmp(buf + 5, "include", 7)) {
8164          do_ssi_include(conn, path, buf + 12, include_level);
8165#if !defined(NO_POPEN)
8166        } else if (!memcmp(buf + 5, "exec", 4)) {
8167          do_ssi_exec(conn, buf + 9);
8168#endif /* !NO_POPEN */
8169        } else {
8170          mg_cry(conn,
8171                 "%s: unknown SSI "
8172                 "command: \"%s\"",
8173                 path,
8174                 buf);
8175        }
8176      }
8177      len = 0;
8178    } else if (in_ssi_tag) {
8179      if (len == 5 && memcmp(buf, "<!--#", 5) != 0) {
8180        /* Not an SSI tag */
8181        in_ssi_tag = 0;
8182      } else if (len == (int)sizeof(buf) - 2) {
8183        mg_cry(conn, "%s: SSI tag is too large", path);
8184        len = 0;
8185      }
8186      buf[len++] = (char)(ch & 0xff);
8187    } else if (ch == '<') {
8188      in_ssi_tag = 1;
8189      if (len > 0) {
8190        mg_write(conn, buf, (size_t)len);
8191      }
8192      len = 0;
8193      buf[len++] = (char)(ch & 0xff);
8194    } else {
8195      buf[len++] = (char)(ch & 0xff);
8196      if (len == (int)sizeof(buf)) {
8197        mg_write(conn, buf, (size_t)len);
8198        len = 0;
8199      }
8200    }
8201  }
8202
8203  /* Send the rest of buffered data */
8204  if (len > 0) {
8205    mg_write(conn, buf, (size_t)len);
8206  }
8207}
8208
8209
8210static void
8211handle_ssi_file_request(struct mg_connection *conn,
8212                        const char *path,
8213                        struct file *filep)
8214{
8215  char date[64];
8216  time_t curtime = time(NULL);
8217  const char *cors1, *cors2, *cors3;
8218
8219  if (conn == NULL || path == NULL || filep == NULL) {
8220    return;
8221  }
8222
8223  if (mg_get_header(conn, "Origin")) {
8224    /* Cross-origin resource sharing (CORS). */
8225    cors1 = "Access-Control-Allow-Origin: ";
8226    cors2 = conn->ctx->config[ACCESS_CONTROL_ALLOW_ORIGIN];
8227    cors3 = "\r\n";
8228  } else {
8229    cors1 = cors2 = cors3 = "";
8230  }
8231
8232  if (!mg_fopen(conn, path, "rb", filep)) {
8233    /* File exists (precondition for calling this function),
8234     * but can not be opened by the server. */
8235    send_http_error(conn,
8236                    500,
8237                    "Error: Cannot read file\nfopen(%s): %s",
8238                    path,
8239                    strerror(ERRNO));
8240  } else {
8241    conn->must_close = 1;
8242    gmt_time_string(date, sizeof(date), &curtime);
8243    fclose_on_exec(filep, conn);
8244    mg_printf(conn, "HTTP/1.1 200 OK\r\n");
8245    send_no_cache_header(conn);
8246    mg_printf(conn,
8247              "%s%s%s"
8248              "Date: %s\r\n"
8249              "Content-Type: text/html\r\n"
8250              "Connection: %s\r\n\r\n",
8251              cors1,
8252              cors2,
8253              cors3,
8254              date,
8255              suggest_connection_header(conn));
8256    send_ssi_file(conn, path, filep, 0);
8257    mg_fclose(filep);
8258  }
8259}
8260
8261
8262#if !defined(NO_FILES)
8263static void
8264send_options(struct mg_connection *conn)
8265{
8266  char date[64];
8267  time_t curtime = time(NULL);
8268
8269  if (!conn) {
8270    return;
8271  }
8272
8273  conn->status_code = 200;
8274  conn->must_close = 1;
8275  gmt_time_string(date, sizeof(date), &curtime);
8276
8277  mg_printf(conn,
8278            "HTTP/1.1 200 OK\r\n"
8279            "Date: %s\r\n"
8280            /* TODO: "Cache-Control" (?) */
8281            "Connection: %s\r\n"
8282            "Allow: GET, POST, HEAD, CONNECT, PUT, DELETE, OPTIONS, "
8283            "PROPFIND, MKCOL\r\n"
8284            "DAV: 1\r\n\r\n",
8285            date,
8286            suggest_connection_header(conn));
8287}
8288
8289
8290/* Writes PROPFIND properties for a collection element */
8291static void
8292print_props(struct mg_connection *conn, const char *uri, struct file *filep)
8293{
8294  char mtime[64];
8295
8296  if (conn == NULL || uri == NULL || filep == NULL) {
8297    return;
8298  }
8299
8300  gmt_time_string(mtime, sizeof(mtime), &filep->last_modified);
8301  conn->num_bytes_sent +=
8302      mg_printf(conn,
8303                "<d:response>"
8304                "<d:href>%s</d:href>"
8305                "<d:propstat>"
8306                "<d:prop>"
8307                "<d:resourcetype>%s</d:resourcetype>"
8308                "<d:getcontentlength>%" INT64_FMT "</d:getcontentlength>"
8309                "<d:getlastmodified>%s</d:getlastmodified>"
8310                "</d:prop>"
8311                "<d:status>HTTP/1.1 200 OK</d:status>"
8312                "</d:propstat>"
8313                "</d:response>\n",
8314                uri,
8315                filep->is_directory ? "<d:collection/>" : "",
8316                filep->size,
8317                mtime);
8318}
8319
8320
8321static void
8322print_dav_dir_entry(struct de *de, void *data)
8323{
8324  char href[PATH_MAX];
8325  char href_encoded[PATH_MAX];
8326  int truncated;
8327
8328  struct mg_connection *conn = (struct mg_connection *)data;
8329  if (!de || !conn) {
8330    return;
8331  }
8332  mg_snprintf(conn,
8333              &truncated,
8334              href,
8335              sizeof(href),
8336              "%s%s",
8337              conn->request_info.local_uri,
8338              de->file_name);
8339
8340  if (!truncated) {
8341    mg_url_encode(href, href_encoded, PATH_MAX - 1);
8342    print_props(conn, href_encoded, &de->file);
8343  }
8344}
8345
8346
8347static void
8348handle_propfind(struct mg_connection *conn,
8349                const char *path,
8350                struct file *filep)
8351{
8352  const char *depth = mg_get_header(conn, "Depth");
8353  char date[64];
8354  time_t curtime = time(NULL);
8355
8356  gmt_time_string(date, sizeof(date), &curtime);
8357
8358  if (!conn || !path || !filep || !conn->ctx) {
8359    return;
8360  }
8361
8362  conn->must_close = 1;
8363  conn->status_code = 207;
8364  mg_printf(conn,
8365            "HTTP/1.1 207 Multi-Status\r\n"
8366            "Date: %s\r\n",
8367            date);
8368  send_static_cache_header(conn);
8369  mg_printf(conn,
8370            "Connection: %s\r\n"
8371            "Content-Type: text/xml; charset=utf-8\r\n\r\n",
8372            suggest_connection_header(conn));
8373
8374  conn->num_bytes_sent +=
8375      mg_printf(conn,
8376                "<?xml version=\"1.0\" encoding=\"utf-8\"?>"
8377                "<d:multistatus xmlns:d='DAV:'>\n");
8378
8379  /* Print properties for the requested resource itself */
8380  print_props(conn, conn->request_info.local_uri, filep);
8381
8382  /* If it is a directory, print directory entries too if Depth is not 0 */
8383  if (filep && filep->is_directory
8384      && !mg_strcasecmp(conn->ctx->config[ENABLE_DIRECTORY_LISTING], "yes")
8385      && (depth == NULL || strcmp(depth, "0") != 0)) {
8386    scan_directory(conn, path, conn, &print_dav_dir_entry);
8387  }
8388
8389  conn->num_bytes_sent += mg_printf(conn, "%s\n", "</d:multistatus>");
8390}
8391#endif
8392
8393void
8394mg_lock_connection(struct mg_connection *conn)
8395{
8396  if (conn) {
8397    (void)pthread_mutex_lock(&conn->mutex);
8398  }
8399}
8400
8401void
8402mg_unlock_connection(struct mg_connection *conn)
8403{
8404  if (conn) {
8405    (void)pthread_mutex_unlock(&conn->mutex);
8406  }
8407}
8408
8409void
8410mg_lock_context(struct mg_context *ctx)
8411{
8412  if (ctx) {
8413    (void)pthread_mutex_lock(&ctx->nonce_mutex);
8414  }
8415}
8416
8417void
8418mg_unlock_context(struct mg_context *ctx)
8419{
8420  if (ctx) {
8421    (void)pthread_mutex_unlock(&ctx->nonce_mutex);
8422  }
8423}
8424
8425#if defined(USE_TIMERS)
8426#include "timer.inl"
8427#endif /* USE_TIMERS */
8428
8429#ifdef USE_LUA
8430#include "mod_lua.inl"
8431#endif /* USE_LUA */
8432
8433#ifdef USE_DUKTAPE
8434#include "mod_duktape.inl"
8435#endif /* USE_DUKTAPE */
8436
8437#if defined(USE_WEBSOCKET)
8438
8439/* START OF SHA-1 code
8440 * Copyright(c) By Steve Reid <steve@edmweb.com> */
8441#define SHA1HANDSOFF
8442
8443/* According to current tests (May 2015), the <solarisfixes.h> is not required.
8444 *
8445 * #if defined(__sun)
8446 * #include "solarisfixes.h"
8447 * #endif
8448 */
8449
8450
8451static int
8452is_big_endian(void)
8453{
8454  static const int n = 1;
8455  return ((char *)&n)[0] == 0;
8456}
8457
8458
8459union char64long16 {
8460  unsigned char c[64];
8461  uint32_t l[16];
8462};
8463
8464#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
8465
8466
8467static uint32_t
8468blk0(union char64long16 *block, int i)
8469{
8470  /* Forrest: SHA expect BIG_ENDIAN, swap if LITTLE_ENDIAN */
8471  if (!is_big_endian()) {
8472    block->l[i] = (rol(block->l[i], 24) & 0xFF00FF00)
8473                  | (rol(block->l[i], 8) & 0x00FF00FF);
8474  }
8475  return block->l[i];
8476}
8477
8478#define blk(i)                                                                 \
8479  (block->l[i & 15] = rol(block->l[(i + 13) & 15] ^ block->l[(i + 8) & 15]   \
8480                              ^ block->l[(i + 2) & 15] ^ block->l[i & 15],   \
8481                          1))
8482#define R0(v, w, x, y, z, i)                                                   \
8483  z += ((w & (x ^ y)) ^ y) + blk0(block, i) + 0x5A827999 + rol(v, 5);        \
8484  w = rol(w, 30);
8485#define R1(v, w, x, y, z, i)                                                   \
8486  z += ((w & (x ^ y)) ^ y) + blk(i) + 0x5A827999 + rol(v, 5);                \
8487  w = rol(w, 30);
8488#define R2(v, w, x, y, z, i)                                                   \
8489  z += (w ^ x ^ y) + blk(i) + 0x6ED9EBA1 + rol(v, 5);                        \
8490  w = rol(w, 30);
8491#define R3(v, w, x, y, z, i)                                                   \
8492  z += (((w | x) & y) | (w & x)) + blk(i) + 0x8F1BBCDC + rol(v, 5);          \
8493  w = rol(w, 30);
8494#define R4(v, w, x, y, z, i)                                                   \
8495  z += (w ^ x ^ y) + blk(i) + 0xCA62C1D6 + rol(v, 5);                        \
8496  w = rol(w, 30);
8497
8498
8499typedef struct {
8500  uint32_t state[5];
8501  uint32_t count[2];
8502  unsigned char buffer[64];
8503} SHA1_CTX;
8504
8505
8506static void
8507SHA1Transform(uint32_t state[5], const unsigned char buffer[64])
8508{
8509  uint32_t a, b, c, d, e;
8510  union char64long16 block[1];
8511
8512  memcpy(block, buffer, 64);
8513  a = state[0];
8514  b = state[1];
8515  c = state[2];
8516  d = state[3];
8517  e = state[4];
8518  R0(a, b, c, d, e, 0);
8519  R0(e, a, b, c, d, 1);
8520  R0(d, e, a, b, c, 2);
8521  R0(c, d, e, a, b, 3);
8522  R0(b, c, d, e, a, 4);
8523  R0(a, b, c, d, e, 5);
8524  R0(e, a, b, c, d, 6);
8525  R0(d, e, a, b, c, 7);
8526  R0(c, d, e, a, b, 8);
8527  R0(b, c, d, e, a, 9);
8528  R0(a, b, c, d, e, 10);
8529  R0(e, a, b, c, d, 11);
8530  R0(d, e, a, b, c, 12);
8531  R0(c, d, e, a, b, 13);
8532  R0(b, c, d, e, a, 14);
8533  R0(a, b, c, d, e, 15);
8534  R1(e, a, b, c, d, 16);
8535  R1(d, e, a, b, c, 17);
8536  R1(c, d, e, a, b, 18);
8537  R1(b, c, d, e, a, 19);
8538  R2(a, b, c, d, e, 20);
8539  R2(e, a, b, c, d, 21);
8540  R2(d, e, a, b, c, 22);
8541  R2(c, d, e, a, b, 23);
8542  R2(b, c, d, e, a, 24);
8543  R2(a, b, c, d, e, 25);
8544  R2(e, a, b, c, d, 26);
8545  R2(d, e, a, b, c, 27);
8546  R2(c, d, e, a, b, 28);
8547  R2(b, c, d, e, a, 29);
8548  R2(a, b, c, d, e, 30);
8549  R2(e, a, b, c, d, 31);
8550  R2(d, e, a, b, c, 32);
8551  R2(c, d, e, a, b, 33);
8552  R2(b, c, d, e, a, 34);
8553  R2(a, b, c, d, e, 35);
8554  R2(e, a, b, c, d, 36);
8555  R2(d, e, a, b, c, 37);
8556  R2(c, d, e, a, b, 38);
8557  R2(b, c, d, e, a, 39);
8558  R3(a, b, c, d, e, 40);
8559  R3(e, a, b, c, d, 41);
8560  R3(d, e, a, b, c, 42);
8561  R3(c, d, e, a, b, 43);
8562  R3(b, c, d, e, a, 44);
8563  R3(a, b, c, d, e, 45);
8564  R3(e, a, b, c, d, 46);
8565  R3(d, e, a, b, c, 47);
8566  R3(c, d, e, a, b, 48);
8567  R3(b, c, d, e, a, 49);
8568  R3(a, b, c, d, e, 50);
8569  R3(e, a, b, c, d, 51);
8570  R3(d, e, a, b, c, 52);
8571  R3(c, d, e, a, b, 53);
8572  R3(b, c, d, e, a, 54);
8573  R3(a, b, c, d, e, 55);
8574  R3(e, a, b, c, d, 56);
8575  R3(d, e, a, b, c, 57);
8576  R3(c, d, e, a, b, 58);
8577  R3(b, c, d, e, a, 59);
8578  R4(a, b, c, d, e, 60);
8579  R4(e, a, b, c, d, 61);
8580  R4(d, e, a, b, c, 62);
8581  R4(c, d, e, a, b, 63);
8582  R4(b, c, d, e, a, 64);
8583  R4(a, b, c, d, e, 65);
8584  R4(e, a, b, c, d, 66);
8585  R4(d, e, a, b, c, 67);
8586  R4(c, d, e, a, b, 68);
8587  R4(b, c, d, e, a, 69);
8588  R4(a, b, c, d, e, 70);
8589  R4(e, a, b, c, d, 71);
8590  R4(d, e, a, b, c, 72);
8591  R4(c, d, e, a, b, 73);
8592  R4(b, c, d, e, a, 74);
8593  R4(a, b, c, d, e, 75);
8594  R4(e, a, b, c, d, 76);
8595  R4(d, e, a, b, c, 77);
8596  R4(c, d, e, a, b, 78);
8597  R4(b, c, d, e, a, 79);
8598  state[0] += a;
8599  state[1] += b;
8600  state[2] += c;
8601  state[3] += d;
8602  state[4] += e;
8603  a = b = c = d = e = 0;
8604  memset(block, '\0', sizeof(block));
8605}
8606
8607
8608static void
8609SHA1Init(SHA1_CTX *context)
8610{
8611  context->state[0] = 0x67452301;
8612  context->state[1] = 0xEFCDAB89;
8613  context->state[2] = 0x98BADCFE;
8614  context->state[3] = 0x10325476;
8615  context->state[4] = 0xC3D2E1F0;
8616  context->count[0] = context->count[1] = 0;
8617}
8618
8619
8620static void
8621SHA1Update(SHA1_CTX *context, const unsigned char *data, uint32_t len)
8622{
8623  uint32_t i, j;
8624
8625  j = context->count[0];
8626  if ((context->count[0] += len << 3) < j) {
8627    context->count[1]++;
8628  }
8629  context->count[1] += (len >> 29);
8630  j = (j >> 3) & 63;
8631  if ((j + len) > 63) {
8632    memcpy(&context->buffer[j], data, (i = 64 - j));
8633    SHA1Transform(context->state, context->buffer);
8634    for (; i + 63 < len; i += 64) {
8635      SHA1Transform(context->state, &data[i]);
8636    }
8637    j = 0;
8638  } else
8639    i = 0;
8640  memcpy(&context->buffer[j], &data[i], len - i);
8641}
8642
8643
8644static void
8645SHA1Final(unsigned char digest[20], SHA1_CTX *context)
8646{
8647  unsigned i;
8648  unsigned char finalcount[8], c;
8649
8650  for (i = 0; i < 8; i++) {
8651    finalcount[i] = (unsigned char)((context->count[(i >= 4 ? 0 : 1)]
8652                                     >> ((3 - (i & 3)) * 8)) & 255);
8653  }
8654  c = 0200;
8655  SHA1Update(context, &c, 1);
8656  while ((context->count[0] & 504) != 448) {
8657    c = 0000;
8658    SHA1Update(context, &c, 1);
8659  }
8660  SHA1Update(context, finalcount, 8);
8661  for (i = 0; i < 20; i++) {
8662    digest[i] = (unsigned char)((context->state[i >> 2]
8663                                 >> ((3 - (i & 3)) * 8)) & 255);
8664  }
8665  memset(context, '\0', sizeof(*context));
8666  memset(&finalcount, '\0', sizeof(finalcount));
8667}
8668/* END OF SHA1 CODE */
8669
8670
8671static int
8672send_websocket_handshake(struct mg_connection *conn, const char *websock_key)
8673{
8674  static const char *magic = "258EAFA5-E914-47DA-95CA-C5AB0DC85B11";
8675  const char *protocol = NULL;
8676  char buf[100], sha[20], b64_sha[sizeof(sha) * 2];
8677  SHA1_CTX sha_ctx;
8678  int truncated;
8679
8680  /* Calculate Sec-WebSocket-Accept reply from Sec-WebSocket-Key. */
8681  mg_snprintf(conn, &truncated, buf, sizeof(buf), "%s%s", websock_key, magic);
8682  if (truncated) {
8683    conn->must_close = 1;
8684    return 0;
8685  }
8686
8687  SHA1Init(&sha_ctx);
8688  SHA1Update(&sha_ctx, (unsigned char *)buf, (uint32_t)strlen(buf));
8689  SHA1Final((unsigned char *)sha, &sha_ctx);
8690  base64_encode((unsigned char *)sha, sizeof(sha), b64_sha);
8691  mg_printf(conn,
8692            "HTTP/1.1 101 Switching Protocols\r\n"
8693            "Upgrade: websocket\r\n"
8694            "Connection: Upgrade\r\n"
8695            "Sec-WebSocket-Accept: %s\r\n",
8696            b64_sha);
8697  protocol = mg_get_header(conn, "Sec-WebSocket-Protocol");
8698  if (protocol) {
8699    /* The protocol is a comma seperated list of names. */
8700    /* The server must only return one value from this list. */
8701    /* First check if it is a list or just a single value. */
8702    const char *sep = strchr(protocol, ',');
8703    if (sep == NULL) {
8704      /* Just a single protocol -> accept it. */
8705      mg_printf(conn, "Sec-WebSocket-Protocol: %s\r\n\r\n", protocol);
8706    } else {
8707      /* Multiple protocols -> accept the first one. */
8708      /* This is just a quick fix if the client offers multiple
8709       * protocols. In order to get the behavior intended by
8710       * RFC 6455 (https://tools.ietf.org/rfc/rfc6455.txt), it is
8711       * required to have a list of websocket subprotocols accepted
8712       * by the server. Then the server must either select a subprotocol
8713       * supported by client and server, or the server has to abort the
8714       * handshake by not returning a Sec-Websocket-Protocol header if
8715       * no subprotocol is acceptable.
8716       */
8717      mg_printf(conn,
8718                "Sec-WebSocket-Protocol: %.*s\r\n\r\n",
8719                (int)(sep - protocol),
8720                protocol);
8721    }
8722    /* TODO: Real subprotocol negotiation instead of just taking the first
8723     * websocket subprotocol suggested by the client. */
8724  } else {
8725    mg_printf(conn, "%s", "\r\n");
8726  }
8727
8728  return 1;
8729}
8730
8731
8732static void
8733read_websocket(struct mg_connection *conn,
8734               mg_websocket_data_handler ws_data_handler,
8735               void *callback_data)
8736{
8737  /* Pointer to the beginning of the portion of the incoming websocket
8738   * message queue.
8739   * The original websocket upgrade request is never removed, so the queue
8740   * begins after it. */
8741  unsigned char *buf = (unsigned char *)conn->buf + conn->request_len;
8742  int n, error, exit_by_callback;
8743
8744  /* body_len is the length of the entire queue in bytes
8745   * len is the length of the current message
8746   * data_len is the length of the current message's data payload
8747   * header_len is the length of the current message's header */
8748  size_t i, len, mask_len = 0, data_len = 0, header_len, body_len;
8749
8750  /* "The masking key is a 32-bit value chosen at random by the client."
8751   * http://tools.ietf.org/html/draft-ietf-hybi-thewebsocketprotocol-17#section-5
8752  */
8753  unsigned char mask[4];
8754
8755  /* data points to the place where the message is stored when passed to
8756   * the
8757   * websocket_data callback.  This is either mem on the stack, or a
8758   * dynamically allocated buffer if it is too large. */
8759  char mem[4096];
8760  char *data = mem;
8761  unsigned char mop; /* mask flag and opcode */
8762  double timeout = -1.0;
8763
8764  if (conn->ctx->config[WEBSOCKET_TIMEOUT]) {
8765    timeout = atoi(conn->ctx->config[WEBSOCKET_TIMEOUT]) / 1000.0;
8766  }
8767  if (
 Recommendations (Experimental)  R1: ((timeout <= 0.0) && (conn[REQUEST_TIMEOUT]))
R2: ((timeout <= 0.0) && (conn->ctx[REQUEST_TIMEOUT]))
R3: ((timeout <= 0.0) && (conn[REQUEST_TIMEOUT]))
R4: ((timeout == REQUEST_TIMEOUT) && (conn[REQUEST_TIMEOUT]))
R5: ((timeout == {const}) && (conn.ctx[REQUEST_TIMEOUT]))
 Score  Issue:  1 unfamiliar pattern(s) detected 
Cost: 13.00, Total Score: 1013.00
Class: complex_2
(
timeout <= 0.0) && (conn->ctx->config[REQUEST_TIMEOUT])) {
8768    timeout = atoi(conn->ctx->config[REQUEST_TIMEOUT]) / 1000.0;
8769  }
8770
8771  mg_set_thread_name("wsock");
8772
8773  /* Loop continuously, reading messages from the socket, invoking the
8774   * callback, and waiting repeatedly until an error occurs. */
8775  while (!conn->ctx->stop_flag) {
8776    header_len = 0;
8777    assert(conn->data_len >= conn->request_len);
8778    if ((body_len = (size_t)(conn->data_len - conn->request_len)) >= 2) {
8779      len = buf[1] & 127;
8780      mask_len = buf[1] & 128 ? 4 : 0;
8781      if (len < 126 && body_len >= mask_len) {
8782        data_len = len;
8783        header_len = 2 + mask_len;
8784      } else if (len == 126 && body_len >= 4 + mask_len) {
8785        header_len = 4 + mask_len;
8786        data_len = ((((size_t)buf[2]) << 8) + buf[3]);
8787      } else if (body_len >= 10 + mask_len) {
8788        header_len = 10 + mask_len;
8789        data_len = (((uint64_t)ntohl(*(uint32_t *)(void *)&buf[2]))
8790                    << 32) + ntohl(*(uint32_t *)(void *)&buf[6]);
8791      }
8792    }
8793
8794    if (header_len > 0 && body_len >= header_len) {
8795      /* Allocate space to hold websocket payload */
8796      data = mem;
8797      if (data_len > sizeof(mem)) {
8798        data = (char *)mg_malloc(data_len);
8799        if (data == NULL) {
8800          /* Allocation failed, exit the loop and then close the
8801           * connection */
8802          mg_cry(conn, "websocket out of memory; closing connection");
8803          break;
8804        }
8805      }
8806
8807      /* Copy the mask before we shift the queue and destroy it */
8808      if (mask_len > 0) {
8809        memcpy(mask, buf + header_len - mask_len, sizeof(mask));
8810      } else {
8811        memset(mask, 0, sizeof(mask));
8812      }
8813
8814      /* Read frame payload from the first message in the queue into
8815       * data and advance the queue by moving the memory in place. */
8816      assert(body_len >= header_len);
8817      if (data_len + header_len > body_len) {
8818        mop = buf[0]; /* current mask and opcode */
8819        /* Overflow case */
8820        len = body_len - header_len;
8821        memcpy(data, buf + header_len, len);
8822        error = 0;
8823        while (len < data_len) {
8824          n = pull(
8825              NULL, conn, data + len, (int)(data_len - len), timeout);
8826          if (n <= 0) {
8827            error = 1;
8828            break;
8829          }
8830          len += (size_t)n;
8831        }
8832        if (error) {
8833          mg_cry(conn, "Websocket pull failed; closing connection");
8834          break;
8835        }
8836        conn->data_len = conn->request_len;
8837      } else {
8838        mop = buf[0]; /* current mask and opcode, overwritten by
8839                       * memmove() */
8840        /* Length of the message being read at the front of the
8841         * queue */
8842        len = data_len + header_len;
8843
8844        /* Copy the data payload into the data pointer for the
8845         * callback */
8846        memcpy(data, buf + header_len, data_len);
8847
8848        /* Move the queue forward len bytes */
8849        memmove(buf, buf + len, body_len - len);
8850
8851        /* Mark the queue as advanced */
8852        conn->data_len -= (int)len;
8853      }
8854
8855      /* Apply mask if necessary */
8856      if (mask_len > 0) {
8857        for (i = 0; i < data_len; ++i) {
8858          data[i] ^= mask[i & 3];
8859        }
8860      }
8861
8862      /* Exit the loop if callback signals to exit (server side),
8863       * or "connection close" opcode received (client side). */
8864      exit_by_callback = 0;
8865      if ((ws_data_handler != NULL)
8866          && !ws_data_handler(conn, mop, data, data_len, callback_data)) {
8867        exit_by_callback = 1;
8868      }
8869
8870      if (data != mem) {
8871        mg_free(data);
8872      }
8873
8874      if (exit_by_callback
8875          || ((mop & 0xf) == WEBSOCKET_OPCODE_CONNECTION_CLOSE)) {
8876        /* Opcode == 8, connection close */
8877        break;
8878      }
8879
8880      /* Not breaking the loop, process next websocket frame. */
8881    } else {
8882      /* Read from the socket into the next available location in the
8883       * message queue. */
8884      if ((n = pull(NULL,
8885                    conn,
8886                    conn->buf + conn->data_len,
8887                    conn->buf_size - conn->data_len,
8888                    timeout)) <= 0) {
8889        /* Error, no bytes read */
8890        break;
8891      }
8892      conn->data_len += n;
8893    }
8894  }
8895
8896  mg_set_thread_name("worker");
8897}
8898
8899
8900static int
8901mg_websocket_write_exec(struct mg_connection *conn,
8902                        int opcode,
8903                        const char *data,
8904                        size_t dataLen,
8905                        uint32_t masking_key)
8906{
8907  unsigned char header[14];
8908  size_t headerLen = 1;
8909
8910  int retval = -1;
8911
8912  header[0] = 0x80 + (opcode & 0xF);
8913
8914  /* Frame format: http://tools.ietf.org/html/rfc6455#section-5.2 */
8915  if (dataLen < 126) {
8916    /* inline 7-bit length field */
8917    header[1] = (unsigned char)dataLen;
8918    headerLen = 2;
8919  } else if (dataLen <= 0xFFFF) {
8920    /* 16-bit length field */
8921    header[1] = 126;
8922    *(uint16_t *)(void *)(header + 2) = htons((uint16_t)dataLen);
8923    headerLen = 4;
8924  } else {
8925    /* 64-bit length field */
8926    header[1] = 127;
8927    *(uint32_t *)(void *)(header + 2) = htonl((uint64_t)dataLen >> 32);
8928    *(uint32_t *)(void *)(header + 6) = htonl(dataLen & 0xFFFFFFFF);
8929    headerLen = 10;
8930  }
8931
8932  if (masking_key) {
8933    /* add mask */
8934    header[1] |= 0x80;
8935    *(uint32_t *)(void *)(header + headerLen) = masking_key;
8936    headerLen += 4;
8937  }
8938
8939
8940  /* Note that POSIX/Winsock's send() is threadsafe
8941   * http://stackoverflow.com/questions/1981372/are-parallel-calls-to-send-recv-on-the-same-socket-valid
8942   * but mongoose's mg_printf/mg_write is not (because of the loop in
8943   * push(), although that is only a problem if the packet is large or
8944   * outgoing buffer is full). */
8945  (void)mg_lock_connection(conn);
8946  retval = mg_write(conn, header, headerLen);
8947  if (dataLen > 0) {
8948    retval = mg_write(conn, data, dataLen);
8949  }
8950  mg_unlock_connection(conn);
8951
8952  return retval;
8953}
8954
8955int
8956mg_websocket_write(struct mg_connection *conn,
8957                   int opcode,
8958                   const char *data,
8959                   size_t dataLen)
8960{
8961  return mg_websocket_write_exec(conn, opcode, data, dataLen, 0);
8962}
8963
8964
8965static void
8966mask_data(const char *in, size_t in_len, uint32_t masking_key, char *out)
8967{
8968  size_t i = 0;
8969
8970  i = 0;
8971  if ((in_len > 3) && ((ptrdiff_t)in % 4) == 0) {
8972    /* Convert in 32 bit words, if data is 4 byte aligned */
8973    while (i < (in_len - 3)) {
8974      *(uint32_t *)(void *)(out + i) =
8975          *(uint32_t *)(void *)(in + i) ^ masking_key;
8976      i += 4;
8977    }
8978  }
8979  if (i != in_len) {
8980    /* convert 1-3 remaining bytes if ((dataLen % 4) != 0)*/
8981    while (i < in_len) {
8982      *(uint8_t *)(void *)(out + i) =
8983          *(uint8_t *)(void *)(in + i)
8984          ^ *(((uint8_t *)&masking_key) + (i % 4));
8985      i++;
8986    }
8987  }
8988}
8989
8990
8991int
8992mg_websocket_client_write(struct mg_connection *conn,
8993                          int opcode,
8994                          const char *data,
8995                          size_t dataLen)
8996{
8997  int retval = -1;
8998  char *masked_data = (char *)mg_malloc(((dataLen + 7) / 4) * 4);
8999  uint32_t masking_key = (uint32_t)get_random();
9000
9001  if (masked_data == NULL) {
9002    /* Return -1 in an error case */
9003    mg_cry(conn,
9004           "Cannot allocate buffer for masked websocket response: "
9005           "Out of memory");
9006    return -1;
9007  }
9008
9009  mask_data(data, dataLen, masking_key, masked_data);
9010
9011  retval = mg_websocket_write_exec(
9012      conn, opcode, masked_data, dataLen, masking_key);
9013  mg_free(masked_data);
9014
9015  return retval;
9016}
9017
9018
9019static void
9020handle_websocket_request(struct mg_connection *conn,
9021                         const char *path,
9022                         int is_callback_resource,
9023                         mg_websocket_connect_handler ws_connect_handler,
9024                         mg_websocket_ready_handler ws_ready_handler,
9025                         mg_websocket_data_handler ws_data_handler,
9026                         mg_websocket_close_handler ws_close_handler,
9027                         void *cbData)
9028{
9029  const char *websock_key = mg_get_header(conn, "Sec-WebSocket-Key");
9030  const char *version = mg_get_header(conn, "Sec-WebSocket-Version");
9031  int lua_websock = 0;
9032
9033#if !defined(USE_LUA)
9034  (void)path;
9035#endif
9036
9037  /* Step 1: Check websocket protocol version. */
9038  /* Step 1.1: Check Sec-WebSocket-Key. */
9039  if (!websock_key) {
9040    /* The RFC standard version (https://tools.ietf.org/html/rfc6455)
9041     * requires a Sec-WebSocket-Key header.
9042     */
9043    /* It could be the hixie draft version
9044     * (http://tools.ietf.org/html/draft-hixie-thewebsocketprotocol-76).
9045     */
9046    const char *key1 = mg_get_header(conn, "Sec-WebSocket-Key1");
9047    const char *key2 = mg_get_header(conn, "Sec-WebSocket-Key2");
9048    char key3[8];
9049
9050    if ((key1 != NULL) && (key2 != NULL)) {
9051      /* This version uses 8 byte body data in a GET request */
9052      conn->content_len = 8;
9053      if (8 == mg_read(conn, key3, 8)) {
9054        /* This is the hixie version */
9055        send_http_error(conn,
9056                        426,
9057                        "%s",
9058                        "Protocol upgrade to RFC 6455 required");
9059        return;
9060      }
9061    }
9062    /* This is an unknown version */
9063    send_http_error(conn, 400, "%s", "Malformed websocket request");
9064    return;
9065  }
9066
9067  /* Step 1.2: Check websocket protocol version. */
9068  /* The RFC version (https://tools.ietf.org/html/rfc6455) is 13. */
9069  if (version == NULL || strcmp(version, "13") != 0) {
9070    /* Reject wrong versions */
9071    send_http_error(conn, 426, "%s", "Protocol upgrade required");
9072    return;
9073  }
9074
9075  /* Step 1.3: Could check for "Host", but we do not really nead this
9076   * value for anything, so just ignore it. */
9077
9078  /* Step 2: If a callback is responsible, call it. */
9079  if (is_callback_resource) {
9080    if (ws_connect_handler != NULL
9081        && ws_connect_handler(conn, cbData) != 0) {
9082      /* C callback has returned non-zero, do not proceed with
9083       * handshake.
9084       */
9085      /* Note that C callbacks are no longer called when Lua is
9086       * responsible, so C can no longer filter callbacks for Lua. */
9087      return;
9088    }
9089  }
9090#if defined(USE_LUA)
9091  /* Step 3: No callback. Check if Lua is responsible. */
9092  else {
9093    /* Step 3.1: Check if Lua is responsible. */
9094    if (conn->ctx->config[LUA_WEBSOCKET_EXTENSIONS]) {
9095      lua_websock =
9096          match_prefix(conn->ctx->config[LUA_WEBSOCKET_EXTENSIONS],
9097                       strlen(
9098                           conn->ctx->config[LUA_WEBSOCKET_EXTENSIONS]),
9099                       path);
9100    }
9101
9102    if (lua_websock) {
9103      /* Step 3.2: Lua is responsible: call it. */
9104      conn->lua_websocket_state = lua_websocket_new(path, conn);
9105      if (!conn->lua_websocket_state) {
9106        /* Lua rejected the new client */
9107        return;
9108      }
9109    }
9110  }
9111#endif
9112
9113  /* Step 4: Check if there is a responsible websocket handler. */
9114  if (!is_callback_resource && !lua_websock) {
9115    /* There is no callback, an Lua is not responsible either. */
9116    /* Reply with a 404 Not Found or with nothing at all?
9117     * TODO (mid): check the websocket standards, how to reply to
9118     * requests to invalid websocket addresses. */
9119    send_http_error(conn, 404, "%s", "Not found");
9120    return;
9121  }
9122
9123  /* Step 5: The websocket connection has been accepted */
9124  if (!send_websocket_handshake(conn, websock_key)) {
9125    send_http_error(conn, 500, "%s", "Websocket handshake failed");
9126    return;
9127  }
9128
9129  /* Step 6: Call the ready handler */
9130  if (is_callback_resource) {
9131    if (ws_ready_handler != NULL) {
9132      ws_ready_handler(conn, cbData);
9133    }
9134#if defined(USE_LUA)
9135  } else if (lua_websock) {
9136    if (!lua_websocket_ready(conn, conn->lua_websocket_state)) {
9137      /* the ready handler returned false */
9138      return;
9139    }
9140#endif
9141  }
9142
9143  /* Step 7: Enter the read loop */
9144  if (is_callback_resource) {
9145    read_websocket(conn, ws_data_handler, cbData);
9146#if defined(USE_LUA)
9147  } else if (lua_websock) {
9148    read_websocket(conn, lua_websocket_data, conn->lua_websocket_state);
9149#endif
9150  }
9151
9152  /* Step 8: Call the close handler */
9153  if (ws_close_handler) {
9154    ws_close_handler(conn, cbData);
9155  }
9156}
9157
9158
9159static int
9160is_websocket_protocol(const struct mg_connection *conn)
9161{
9162  const char *upgrade, *connection;
9163
9164  /* A websocket protocoll has the following HTTP headers:
9165   *
9166   * Connection: Upgrade
9167   * Upgrade: Websocket
9168   */
9169
9170  upgrade = mg_get_header(conn, "Upgrade");
9171  if (upgrade == NULL) {
9172    return 0; /* fail early, don't waste time checking other header
9173               * fields
9174                 */
9175  }
9176  if (!mg_strcasestr(upgrade, "websocket")) {
9177    return 0;
9178  }
9179
9180  connection = mg_get_header(conn, "Connection");
9181  if (connection == NULL) {
9182    return 0;
9183  }
9184  if (!mg_strcasestr(connection, "upgrade")) {
9185    return 0;
9186  }
9187
9188  /* The headers "Host", "Sec-WebSocket-Key", "Sec-WebSocket-Protocol" and
9189   * "Sec-WebSocket-Version" are also required.
9190   * Don't check them here, since even an unsupported websocket protocol
9191   * request still IS a websocket request (in contrast to a standard HTTP
9192   * request). It will fail later in handle_websocket_request.
9193   */
9194
9195  return 1;
9196}
9197#endif /* !USE_WEBSOCKET */
9198
9199
9200static int
9201isbyte(int n)
9202{
9203  return n >= 0 && n <= 255;
9204}
9205
9206
9207static int
9208parse_net(const char *spec, uint32_t *net, uint32_t *mask)
9209{
9210  int n, a, b, c, d, slash = 32, len = 0;
9211
9212  if ((sscanf(spec, "%d.%d.%d.%d/%d%n", &a, &b, &c, &d, &slash, &n) == 5
9213       || sscanf(spec, "%d.%d.%d.%d%n", &a, &b, &c, &d, &n) == 4) && isbyte(a)
9214      && isbyte(b) && isbyte(c) && isbyte(d) && slash >= 0
9215      && slash < 33) {
9216    len = n;
9217    *net = ((uint32_t)a << 24) | ((uint32_t)b << 16) | ((uint32_t)c << 8)
9218           | (uint32_t)d;
9219    *mask = slash ? 0xffffffffU << (32 - slash) : 0;
9220  }
9221
9222  return len;
9223}
9224
9225
9226static int
9227set_throttle(const char *spec, uint32_t remote_ip, const char *uri)
9228{
9229  int throttle = 0;
9230  struct vec vec, val;
9231  uint32_t net, mask;
9232  char mult;
9233  double v;
9234
9235  while ((spec = next_option(spec, &vec, &val)) != NULL) {
9236    mult = ',';
9237    if (sscanf(val.ptr, "%lf%c", &v, &mult) < 1 || v < 0
9238        || (lowercase(&mult) != 'k' && lowercase(&mult) != 'm'
9239            && mult != ',')) {
9240      continue;
9241    }
9242    v *= lowercase(&mult) == 'k' ? 1024 : lowercase(&mult) == 'm' ? 1048576
9243                                                                  : 1;
9244    if (vec.len == 1 && vec.ptr[0] == '*') {
9245      throttle = (int)v;
9246    } else if (parse_net(vec.ptr, &net, &mask) > 0) {
9247      if ((remote_ip & mask) == net) {
9248        throttle = (int)v;
9249      }
9250    } else if (match_prefix(vec.ptr, vec.len, uri) > 0) {
9251      throttle = (int)v;
9252    }
9253  }
9254
9255  return throttle;
9256}
9257
9258
9259static uint32_t
9260get_remote_ip(const struct mg_connection *conn)
9261{
9262  if (!conn) {
9263    return 0;
9264  }
9265  return ntohl(*(const uint32_t *)&conn->client.rsa.sin.sin_addr);
9266}
9267
9268
9269/* The mg_upload function is superseeded by mg_handle_form_request. */
9270#include "handle_form.inl"
9271
9272
9273#if defined(MG_LEGACY_INTERFACE)
9274/* Implement the deprecated mg_upload function by calling the new
9275 * mg_handle_form_request function. While mg_upload could only handle
9276 * HTML forms sent as POST request in multipart/form-data format
9277 * containing only file input elements, mg_handle_form_request can
9278 * handle all form input elements and all standard request methods. */
9279struct mg_upload_user_data {
9280  struct mg_connection *conn;
9281  const char *destination_dir;
9282  int num_uploaded_files;
9283};
9284
9285
9286/* Helper function for deprecated mg_upload. */
9287static int
9288mg_upload_field_found(const char *key,
9289                      const char *filename,
9290                      char *path,
9291                      size_t pathlen,
9292                      void *user_data)
9293{
9294  int truncated = 0;
9295  struct mg_upload_user_data *fud = (struct mg_upload_user_data *)user_data;
9296  (void)key;
9297
9298  if (!filename) {
9299    mg_cry(fud->conn, "%s: No filename set", __func__);
9300    return FORM_FIELD_STORAGE_ABORT;
9301  }
9302  mg_snprintf(fud->conn,
9303              &truncated,
9304              path,
9305              pathlen - 1,
9306              "%s/%s",
9307              fud->destination_dir,
9308              filename);
9309  if (!truncated) {
9310    mg_cry(fud->conn, "%s: File path too long", __func__);
9311    return FORM_FIELD_STORAGE_ABORT;
9312  }
9313  return FORM_FIELD_STORAGE_STORE;
9314}
9315
9316
9317/* Helper function for deprecated mg_upload. */
9318static int
9319mg_upload_field_get(const char *key,
9320                    const char *value,
9321                    size_t value_size,
9322                    void *user_data)
9323{
9324  /* Function should never be called */
9325  (void)key;
9326  (void)value;
9327  (void)value_size;
9328  (void)user_data;
9329
9330  return 0;
9331}
9332
9333
9334/* Helper function for deprecated mg_upload. */
9335static int
9336mg_upload_field_stored(const char *path, long long file_size, void *user_data)
9337{
9338  struct mg_upload_user_data *fud = (struct mg_upload_user_data *)user_data;
9339  (void)file_size;
9340
9341  fud->num_uploaded_files++;
9342  fud->conn->ctx->callbacks.upload(fud->conn, path);
9343
9344  return 0;
9345}
9346
9347
9348/* Deprecated function mg_upload - use mg_handle_form_request instead. */
9349int
9350mg_upload(struct mg_connection *conn, const char *destination_dir)
9351{
9352  struct mg_upload_user_data fud = {conn, destination_dir, 0};
9353  struct mg_form_data_handler fdh = {mg_upload_field_found,
9354                                     mg_upload_field_get,
9355                                     mg_upload_field_stored,
9356                                     0};
9357  int ret;
9358
9359  fdh.user_data = (void *)&fud;
9360  ret = mg_handle_form_request(conn, &fdh);
9361
9362  if (ret < 0) {
9363    mg_cry(conn, "%s: Error while parsing the request", __func__);
9364  }
9365
9366  return fud.num_uploaded_files;
9367}
9368#endif
9369
9370
9371static int
9372get_first_ssl_listener_index(const struct mg_context *ctx)
9373{
9374  unsigned int i;
9375  int idx = -1;
9376  if (ctx) {
9377    for (i = 0; idx == -1 && i < ctx->num_listening_sockets; i++) {
9378      idx = ctx->listening_sockets[i].is_ssl ? ((int)(i)) : -1;
9379    }
9380  }
9381  return idx;
9382}
9383
9384
9385static void
9386redirect_to_https_port(struct mg_connection *conn, int ssl_index)
9387{
9388  char host[1025];
9389  const char *host_header;
9390  size_t hostlen;
9391
9392  host_header = mg_get_header(conn, "Host");
9393  hostlen = sizeof(host);
9394  if (host_header != NULL) {
9395    char *pos;
9396
9397    mg_strlcpy(host, host_header, hostlen);
9398    host[hostlen - 1] = '\0';
9399    pos = strchr(host, ':');
9400    if (pos != NULL) {
9401      *pos = '\0';
9402    }
9403  } else {
9404    /* Cannot get host from the Host: header.
9405     * Fallback to our IP address. */
9406    if (conn) {
9407      sockaddr_to_string(host, hostlen, &conn->client.lsa);
9408    }
9409  }
9410
9411  /* Send host, port, uri and (if it exists) ?query_string */
9412  if (conn) {
9413    mg_printf(conn,
9414              "HTTP/1.1 302 Found\r\nLocation: https://%s:%d%s%s%s\r\n\r\n",
9415              host,
9416              (int)ntohs(
9417                  conn->ctx->listening_sockets[ssl_index].lsa.sin.sin_port),
9418              conn->request_info.local_uri,
9419              (conn->request_info.query_string == NULL) ? "" : "?",
9420              (conn->request_info.query_string == NULL)
9421                  ? ""
9422                  : conn->request_info.query_string);
9423  }
9424}
9425
9426
9427static void
9428mg_set_handler_type(struct mg_context *ctx,
9429                    const char *uri,
9430                    int handler_type,
9431                    int is_delete_request,
9432                    mg_request_handler handler,
9433                    mg_websocket_connect_handler connect_handler,
9434                    mg_websocket_ready_handler ready_handler,
9435                    mg_websocket_data_handler data_handler,
9436                    mg_websocket_close_handler close_handler,
9437                    mg_authorization_handler auth_handler,
9438                    void *cbdata)
9439{
9440  struct mg_handler_info *tmp_rh, **lastref;
9441  size_t urilen = strlen(uri);
9442
9443  if (handler_type == WEBSOCKET_HANDLER) {
9444    /* assert(handler == NULL); */
9445    /* assert(is_delete_request || connect_handler!=NULL ||
9446     *        ready_handler!=NULL || data_handler!=NULL ||
9447     *        close_handler!=NULL);
9448     */
9449    /* assert(auth_handler == NULL); */
9450    if (handler != NULL) {
9451      return;
9452    }
9453    if (
 Recommendations (Experimental)  R1: (is_delete_request = connect_handler == NULL)
R2: (is_delete_request = connect_handler != NULL)
R3: (is_delete_request = (connect_handler != NULL))
R4: (is_delete_request = (connect_handler == NULL))
R5: (is_delete_request.connect_handler = (ready_handler != NULL))
 Score  Issue:  1 unfamiliar pattern(s) detected 
Cost: 21.00, Total Score: 1021.00
Class: complex_1
!
is_delete_request && connect_handler == NULL
9454        && ready_handler == NULL
9455        && data_handler == NULL
9456        && close_handler == NULL) {
9457      return;
9458    }
9459    if (auth_handler != NULL) {
9460      return;
9461    }
9462  } else if (handler_type == REQUEST_HANDLER) {
9463    /* assert(connect_handler==NULL && ready_handler==NULL &&
9464     *        data_handler==NULL && close_handler==NULL); */
9465    /* assert(is_delete_request || (handler!=NULL));
9466     */
9467    /* assert(auth_handler == NULL); */
9468    if (connect_handler != NULL || ready_handler != NULL
9469        || data_handler != NULL
9470        || close_handler != NULL) {
9471      return;
9472    }
9473    if (!is_delete_request && (handler == NULL)) {
9474      return;
9475    }
9476    if (auth_handler != NULL) {
9477      return;
9478    }
9479  } else { /* AUTH_HANDLER */
9480         /* assert(handler == NULL); */
9481         /* assert(connect_handler==NULL && ready_handler==NULL &&
9482          *        data_handler==NULL && close_handler==NULL); */
9483    /* assert(auth_handler != NULL); */
9484    if (handler != NULL) {
9485      return;
9486    }
9487    if (connect_handler != NULL || ready_handler != NULL
9488        || data_handler != NULL
9489        || close_handler != NULL) {
9490      return;
9491    }
9492    if (!is_delete_request && (auth_handler == NULL)) {
9493      return;
9494    }
9495  }
9496
9497  if (!ctx) {
9498    return;
9499  }
9500
9501  mg_lock_context(ctx);
9502
9503  /* first try to find an existing handler */
9504  lastref = &(ctx->handlers);
9505  for (tmp_rh = ctx->handlers; tmp_rh != NULL; tmp_rh = tmp_rh->next) {
9506    if (tmp_rh->handler_type == handler_type) {
9507      if (urilen == tmp_rh->uri_len && !strcmp(tmp_rh->uri, uri)) {
9508        if (!is_delete_request) {
9509          /* update existing handler */
9510          if (handler_type == REQUEST_HANDLER) {
9511            tmp_rh->handler = handler;
9512          } else if (handler_type == WEBSOCKET_HANDLER) {
9513            tmp_rh->connect_handler = connect_handler;
9514            tmp_rh->ready_handler = ready_handler;
9515            tmp_rh->data_handler = data_handler;
9516            tmp_rh->close_handler = close_handler;
9517          } else { /* AUTH_HANDLER */
9518            tmp_rh->auth_handler = auth_handler;
9519          }
9520          tmp_rh->cbdata = cbdata;
9521        } else {
9522          /* remove existing handler */
9523          *lastref = tmp_rh->next;
9524          mg_free(tmp_rh->uri);
9525          mg_free(tmp_rh);
9526        }
9527        mg_unlock_context(ctx);
9528        return;
9529      }
9530    }
9531    lastref = &(tmp_rh->next);
9532  }
9533
9534  if (is_delete_request) {
9535    /* no handler to set, this was a remove request to a non-existing
9536     * handler */
9537    mg_unlock_context(ctx);
9538    return;
9539  }
9540
9541  tmp_rh =
9542      (struct mg_handler_info *)mg_calloc(sizeof(struct mg_handler_info), 1);
9543  if (tmp_rh == NULL) {
9544    mg_unlock_context(ctx);
9545    mg_cry(fc(ctx), "%s", "Cannot create new request handler struct, OOM");
9546    return;
9547  }
9548  tmp_rh->uri = mg_strdup(uri);
9549  if (!tmp_rh->uri) {
9550    mg_unlock_context(ctx);
9551    mg_free(tmp_rh);
9552    mg_cry(fc(ctx), "%s", "Cannot create new request handler struct, OOM");
9553    return;
9554  }
9555  tmp_rh->uri_len = urilen;
9556  if (handler_type == REQUEST_HANDLER) {
9557    tmp_rh->handler = handler;
9558  } else if (handler_type == WEBSOCKET_HANDLER) {
9559    tmp_rh->connect_handler = connect_handler;
9560    tmp_rh->ready_handler = ready_handler;
9561    tmp_rh->data_handler = data_handler;
9562    tmp_rh->close_handler = close_handler;
9563  } else { /* AUTH_HANDLER */
9564    tmp_rh->auth_handler = auth_handler;
9565  }
9566  tmp_rh->cbdata = cbdata;
9567  tmp_rh->handler_type = handler_type;
9568  tmp_rh->next = NULL;
9569
9570  *lastref = tmp_rh;
9571  mg_unlock_context(ctx);
9572}
9573
9574
9575void
9576mg_set_request_handler(struct mg_context *ctx,
9577                       const char *uri,
9578                       mg_request_handler handler,
9579                       void *cbdata)
9580{
9581  mg_set_handler_type(ctx,
9582                      uri,
9583                      REQUEST_HANDLER,
9584                      handler == NULL,
9585                      handler,
9586                      NULL,
9587                      NULL,
9588                      NULL,
9589                      NULL,
9590                      NULL,
9591                      cbdata);
9592}
9593
9594
9595void
9596mg_set_websocket_handler(struct mg_context *ctx,
9597                         const char *uri,
9598                         mg_websocket_connect_handler connect_handler,
9599                         mg_websocket_ready_handler ready_handler,
9600                         mg_websocket_data_handler data_handler,
9601                         mg_websocket_close_handler close_handler,
9602                         void *cbdata)
9603{
9604  int is_delete_request = (connect_handler == NULL) && (ready_handler == NULL)
9605                          && (data_handler == NULL)
9606                          && (close_handler == NULL);
9607  mg_set_handler_type(ctx,
9608                      uri,
9609                      WEBSOCKET_HANDLER,
9610                      is_delete_request,
9611                      NULL,
9612                      connect_handler,
9613                      ready_handler,
9614                      data_handler,
9615                      close_handler,
9616                      NULL,
9617                      cbdata);
9618}
9619
9620
9621void
9622mg_set_auth_handler(struct mg_context *ctx,
9623                    const char *uri,
9624                    mg_request_handler handler,
9625                    void *cbdata)
9626{
9627  mg_set_handler_type(ctx,
9628                      uri,
9629                      AUTH_HANDLER,
9630                      handler == NULL,
9631                      NULL,
9632                      NULL,
9633                      NULL,
9634                      NULL,
9635                      NULL,
9636                      handler,
9637                      cbdata);
9638}
9639
9640
9641static int
9642get_request_handler(struct mg_connection *conn,
9643                    int handler_type,
9644                    mg_request_handler *handler,
9645                    mg_websocket_connect_handler *connect_handler,
9646                    mg_websocket_ready_handler *ready_handler,
9647                    mg_websocket_data_handler *data_handler,
9648                    mg_websocket_close_handler *close_handler,
9649                    mg_authorization_handler *auth_handler,
9650                    void **cbdata)
9651{
9652  const struct mg_request_info *request_info = mg_get_request_info(conn);
9653  if (request_info) {
9654    const char *uri = request_info->local_uri;
9655    size_t urilen = strlen(uri);
9656    struct mg_handler_info *tmp_rh;
9657
9658    if (!conn || !conn->ctx) {
9659      return 0;
9660    }
9661
9662    mg_lock_context(conn->ctx);
9663
9664    /* first try for an exact match */
9665    for (tmp_rh = conn->ctx->handlers; tmp_rh != NULL;
9666         tmp_rh = tmp_rh->next) {
9667      if (tmp_rh->handler_type == handler_type) {
9668        if (urilen == tmp_rh->uri_len && !strcmp(tmp_rh->uri, uri)) {
9669          if (handler_type == WEBSOCKET_HANDLER) {
9670            *connect_handler = tmp_rh->connect_handler;
9671            *ready_handler = tmp_rh->ready_handler;
9672            *data_handler = tmp_rh->data_handler;
9673            *close_handler = tmp_rh->close_handler;
9674          } else if (handler_type == REQUEST_HANDLER) {
9675            *handler = tmp_rh->handler;
9676          } else { /* AUTH_HANDLER */
9677            *auth_handler = tmp_rh->auth_handler;
9678          }
9679          *cbdata = tmp_rh->cbdata;
9680          mg_unlock_context(conn->ctx);
9681          return 1;
9682        }
9683      }
9684    }
9685
9686    /* next try for a partial match, we will accept uri/something */
9687    for (tmp_rh = conn->ctx->handlers; tmp_rh != NULL;
9688         tmp_rh = tmp_rh->next) {
9689      if (tmp_rh->handler_type == handler_type) {
9690        if (tmp_rh->uri_len < urilen && uri[tmp_rh->uri_len] == '/'
9691            && memcmp(tmp_rh->uri, uri, tmp_rh->uri_len) == 0) {
9692          if (handler_type == WEBSOCKET_HANDLER) {
9693            *connect_handler = tmp_rh->connect_handler;
9694            *ready_handler = tmp_rh->ready_handler;
9695            *data_handler = tmp_rh->data_handler;
9696            *close_handler = tmp_rh->close_handler;
9697          } else if (handler_type == REQUEST_HANDLER) {
9698            *handler = tmp_rh->handler;
9699          } else { /* AUTH_HANDLER */
9700            *auth_handler = tmp_rh->auth_handler;
9701          }
9702          *cbdata = tmp_rh->cbdata;
9703          mg_unlock_context(conn->ctx);
9704          return 1;
9705        }
9706      }
9707    }
9708
9709    /* finally try for pattern match */
9710    for (tmp_rh = conn->ctx->handlers; tmp_rh != NULL;
9711         tmp_rh = tmp_rh->next) {
9712      if (tmp_rh->handler_type == handler_type) {
9713        if (match_prefix(tmp_rh->uri, tmp_rh->uri_len, uri) > 0) {
9714          if (handler_type == WEBSOCKET_HANDLER) {
9715            *connect_handler = tmp_rh->connect_handler;
9716            *ready_handler = tmp_rh->ready_handler;
9717            *data_handler = tmp_rh->data_handler;
9718            *close_handler = tmp_rh->close_handler;
9719          } else if (handler_type == REQUEST_HANDLER) {
9720            *handler = tmp_rh->handler;
9721          } else { /* AUTH_HANDLER */
9722            *auth_handler = tmp_rh->auth_handler;
9723          }
9724          *cbdata = tmp_rh->cbdata;
9725          mg_unlock_context(conn->ctx);
9726          return 1;
9727        }
9728      }
9729    }
9730
9731    mg_unlock_context(conn->ctx);
9732  }
9733  return 0; /* none found */
9734}
9735
9736
9737#if defined(USE_WEBSOCKET) && defined(MG_LEGACY_INTERFACE)
9738static int
9739deprecated_websocket_connect_wrapper(const struct mg_connection *conn,
9740                                     void *cbdata)
9741{
9742  struct mg_callbacks *pcallbacks = (struct mg_callbacks *)cbdata;
9743  if (pcallbacks->websocket_connect) {
9744    return pcallbacks->websocket_connect(conn);
9745  }
9746  /* No handler set - assume "OK" */
9747  return 0;
9748}
9749
9750
9751static void
9752deprecated_websocket_ready_wrapper(struct mg_connection *conn, void *cbdata)
9753{
9754  struct mg_callbacks *pcallbacks = (struct mg_callbacks *)cbdata;
9755  if (pcallbacks->websocket_ready) {
9756    pcallbacks->websocket_ready(conn);
9757  }
9758}
9759
9760
9761static int
9762deprecated_websocket_data_wrapper(struct mg_connection *conn,
9763                                  int bits,
9764                                  char *data,
9765                                  size_t len,
9766                                  void *cbdata)
9767{
9768  struct mg_callbacks *pcallbacks = (struct mg_callbacks *)cbdata;
9769  if (pcallbacks->websocket_data) {
9770    return pcallbacks->websocket_data(conn, bits, data, len);
9771  }
9772  /* No handler set - assume "OK" */
9773  return 1;
9774}
9775#endif
9776
9777
9778/* This is the heart of the Civetweb's logic.
9779 * This function is called when the request is read, parsed and validated,
9780 * and Civetweb must decide what action to take: serve a file, or
9781 * a directory, or call embedded function, etcetera. */
9782static void
9783handle_request(struct mg_connection *conn)
9784{
9785  if (conn) {
9786    struct mg_request_info *ri = &conn->request_info;
9787    char path[PATH_MAX];
9788    int uri_len, ssl_index;
9789    int is_found = 0, is_script_resource = 0, is_websocket_request = 0,
9790        is_put_or_delete_request = 0, is_callback_resource = 0;
9791    int i;
9792    struct file file = STRUCT_FILE_INITIALIZER;
9793    mg_request_handler callback_handler = NULL;
9794    mg_websocket_connect_handler ws_connect_handler = NULL;
9795    mg_websocket_ready_handler ws_ready_handler = NULL;
9796    mg_websocket_data_handler ws_data_handler = NULL;
9797    mg_websocket_close_handler ws_close_handler = NULL;
9798    void *callback_data = NULL;
9799    mg_authorization_handler auth_handler = NULL;
9800    void *auth_callback_data = NULL;
9801#if !defined(NO_FILES)
9802    time_t curtime = time(NULL);
9803    char date[64];
9804#endif
9805
9806    path[0] = 0;
9807
9808    if (!ri) {
9809      return;
9810    }
9811
9812    /* 1. get the request url */
9813    /* 1.1. split into url and query string */
9814    if ((conn->request_info.query_string = strchr(ri->request_uri, '?'))
9815        != NULL) {
9816      *((char *)conn->request_info.query_string++) = '\0';
9817    }
9818    uri_len = (int)strlen(ri->local_uri);
9819
9820    /* 1.2. decode url (if config says so) */
9821    if (should_decode_url(conn)) {
9822      mg_url_decode(
9823          ri->local_uri, uri_len, (char *)ri->local_uri, uri_len + 1, 0);
9824    }
9825
9826    /* 1.3. clean URIs, so a path like allowed_dir/../forbidden_file is
9827     * not possible */
9828    remove_double_dots_and_double_slashes((char *)ri->local_uri);
9829
9830    /* step 1. completed, the url is known now */
9831    DEBUG_TRACE("URL: %s", ri->local_uri);
9832
9833    /* 2. do a https redirect, if required */
9834    if (!conn->client.is_ssl && conn->client.ssl_redir) {
9835      ssl_index = get_first_ssl_listener_index(conn->ctx);
9836      if (ssl_index >= 0) {
9837        redirect_to_https_port(conn, ssl_index);
9838      } else {
9839        /* A http to https forward port has been specified,
9840         * but no https port to forward to. */
9841        send_http_error(conn,
9842                        503,
9843                        "%s",
9844                        "Error: SSL forward not configured properly");
9845        mg_cry(conn, "Can not redirect to SSL, no SSL port available");
9846      }
9847      return;
9848    }
9849
9850    /* 3. if this ip has limited speed, set it for this connection */
9851    conn->throttle = set_throttle(conn->ctx->config[THROTTLE],
9852                                  get_remote_ip(conn),
9853                                  ri->local_uri);
9854
9855    /* 4. call a "handle everything" callback, if registered */
9856    if (conn->ctx->callbacks.begin_request != NULL) {
9857      /* Note that since V1.7 the "begin_request" function is called
9858       * before an authorization check. If an authorization check is
9859       * required, use a request_handler instead. */
9860      i = conn->ctx->callbacks.begin_request(conn);
9861      if (i > 0) {
9862        /* callback already processed the request. Store the
9863           return value as a status code for the access log. */
9864        conn->status_code = i;
9865        return;
9866      } else if (i == 0) {
9867        /* civetweb should process the request */
9868      } else {
9869        /* unspecified - may change with the next version */
9870        return;
9871      }
9872    }
9873
9874    /* request not yet handled by a handler or redirect, so the request
9875     * is processed here */
9876
9877    /* 5. interpret the url to find out how the request must be handled
9878     */
9879    /* 5.1. first test, if the request targets the regular http(s)://
9880     * protocol namespace or the websocket ws(s):// protocol namespace.
9881     */
9882    is_websocket_request = is_websocket_protocol(conn);
9883
9884    /* 5.2. check if the request will be handled by a callback */
9885    if (get_request_handler(conn,
9886                            is_websocket_request ? WEBSOCKET_HANDLER
9887                                                 : REQUEST_HANDLER,
9888                            &callback_handler,
9889                            &ws_connect_handler,
9890                            &ws_ready_handler,
9891                            &ws_data_handler,
9892                            &ws_close_handler,
9893                            NULL,
9894                            &callback_data)) {
9895      /* 5.2.1. A callback will handle this request. All requests
9896       * handled
9897       * by a callback have to be considered as requests to a script
9898       * resource. */
9899      is_callback_resource = 1;
9900      is_script_resource = 1;
9901      is_put_or_delete_request = is_put_or_delete_method(conn);
9902    } else {
9903    no_callback_resource:
9904      /* 5.2.2. No callback is responsible for this request. The URI
9905       * addresses a file based resource (static content or Lua/cgi
9906       * scripts in the file system). */
9907      is_callback_resource = 0;
9908      interpret_uri(conn,
9909                    path,
9910                    sizeof(path),
9911                    &file,
9912                    &is_found,
9913                    &is_script_resource,
9914                    &is_websocket_request,
9915                    &is_put_or_delete_request);
9916    }
9917
9918    /* 6. authorization check */
9919    /* 6.1. a custom authorization handler is installed */
9920    if (get_request_handler(conn,
9921                            AUTH_HANDLER,
9922                            NULL,
9923                            NULL,
9924                            NULL,
9925                            NULL,
9926                            NULL,
9927                            &auth_handler,
9928                            &auth_callback_data)) {
9929      if (!auth_handler(conn, auth_callback_data)) {
9930        return;
9931      }
9932    } else if (is_put_or_delete_request && !is_script_resource
9933               && !is_callback_resource) {
9934/* 6.2. this request is a PUT/DELETE to a real file */
9935/* 6.2.1. thus, the server must have real files */
9936#if defined(NO_FILES)
9937      if (1) {
9938#else
9939      if (conn->ctx->config[DOCUMENT_ROOT] == NULL) {
9940#endif
9941        /* This server does not have any real files, thus the
9942         * PUT/DELETE methods are not valid. */
9943        send_http_error(conn,
9944                        405,
9945                        "%s method not allowed",
9946                        conn->request_info.request_method);
9947        return;
9948      }
9949
9950#if !defined(NO_FILES)
9951      /* 6.2.2. Check if put authorization for static files is
9952       * available.
9953       */
9954      if (!is_authorized_for_put(conn)) {
9955        send_authorization_request(conn);
9956        return;
9957      }
9958#endif
9959
9960    } else {
9961      /* 6.3. This is either a OPTIONS, GET, HEAD or POST request,
9962       * or it is a PUT or DELETE request to a resource that does not
9963       * correspond to a file. Check authorization. */
9964      if (!check_authorization(conn, path)) {
9965        send_authorization_request(conn);
9966        return;
9967      }
9968    }
9969
9970    /* request is authorized or does not need authorization */
9971
9972    /* 7. check if there are request handlers for this uri */
9973    if (is_callback_resource) {
9974      if (!is_websocket_request) {
9975        i = callback_handler(conn, callback_data);
9976        if (i > 0) {
9977          /* Do nothing, callback has served the request. Store
9978           * the
9979           * return value as status code for the log and discard
9980           * all
9981           * data from the client not used by the callback. */
9982          conn->status_code = i;
9983          discard_unread_request_data(conn);
9984        } else {
9985          /* TODO (high): what if the handler did NOT handle the
9986           * request */
9987          /* The last version did handle this as a file request,
9988           * but
9989           * since a file request is not always a script resource,
9990           * the authorization check might be different */
9991          interpret_uri(conn,
9992                        path,
9993                        sizeof(path),
9994                        &file,
9995                        &is_found,
9996                        &is_script_resource,
9997                        &is_websocket_request,
9998                        &is_put_or_delete_request);
9999          callback_handler = NULL;
10000
10001          /* TODO (very low): goto is deprecated but for the
10002           * moment,
10003           * a goto is simpler than some curious loop. */
10004          /* The situation "callback does not handle the request"
10005           * needs to be reconsidered anyway. */
10006          goto no_callback_resource;
10007        }
10008      } else {
10009#if defined(USE_WEBSOCKET)
10010        handle_websocket_request(conn,
10011                                 path,
10012                                 is_callback_resource,
10013                                 ws_connect_handler,
10014                                 ws_ready_handler,
10015                                 ws_data_handler,
10016                                 ws_close_handler,
10017                                 callback_data);
10018#endif
10019      }
10020      return;
10021    }
10022
10023/* 8. handle websocket requests */
10024#if defined(USE_WEBSOCKET)
10025    if (is_websocket_request) {
10026      if (is_script_resource) {
10027        /* Websocket Lua script */
10028        handle_websocket_request(conn,
10029                                 path,
10030                                 0 /* Lua Script */,
10031                                 NULL,
10032                                 NULL,
10033                                 NULL,
10034                                 NULL,
10035                                 &conn->ctx->callbacks);
10036      } else {
10037#if defined(MG_LEGACY_INTERFACE)
10038        handle_websocket_request(
10039            conn,
10040            path,
10041            !is_script_resource /* could be deprecated global callback */,
10042            deprecated_websocket_connect_wrapper,
10043            deprecated_websocket_ready_wrapper,
10044            deprecated_websocket_data_wrapper,
10045            NULL,
10046            &conn->ctx->callbacks);
10047#else
10048        send_http_error(conn, 404, "%s", "Not found");
10049#endif
10050      }
10051      return;
10052    } else
10053#endif
10054
10055#if defined(NO_FILES)
10056      /* 9a. In case the server uses only callbacks, this uri is
10057       * unknown.
10058       * Then, all request handling ends here. */
10059      send_http_error(conn, 404, "%s", "Not Found");
10060
10061#else
10062    /* 9b. This request is either for a static file or resource handled
10063     * by a script file. Thus, a DOCUMENT_ROOT must exist. */
10064    if (conn->ctx->config[DOCUMENT_ROOT] == NULL) {
10065      send_http_error(conn, 404, "%s", "Not Found");
10066      return;
10067    }
10068
10069    /* 10. File is handled by a script. */
10070    if (is_script_resource) {
10071      handle_file_based_request(conn, path, &file);
10072      return;
10073    }
10074
10075    /* 11. Handle put/delete/mkcol requests */
10076    if (is_put_or_delete_request) {
10077      /* 11.1. PUT method */
10078      if (!strcmp(ri->request_method, "PUT")) {
10079        put_file(conn, path);
10080        return;
10081      }
10082      /* 11.2. DELETE method */
10083      if (!strcmp(ri->request_method, "DELETE")) {
10084        delete_file(conn, path);
10085        return;
10086      }
10087      /* 11.3. MKCOL method */
10088      if (!strcmp(ri->request_method, "MKCOL")) {
10089        mkcol(conn, path);
10090        return;
10091      }
10092      /* 11.4. PATCH method
10093       * This method is not supported for static resources,
10094       * only for scripts (Lua, CGI) and callbacks. */
10095      send_http_error(conn,
10096                      405,
10097                      "%s method not allowed",
10098                      conn->request_info.request_method);
10099      return;
10100    }
10101
10102    /* 11. File does not exist, or it was configured that it should be
10103     * hidden */
10104    if (!is_found || (must_hide_file(conn, path))) {
10105      send_http_error(conn, 404, "%s", "Not found");
10106      return;
10107    }
10108
10109    /* 12. Directory uris should end with a slash */
10110    if (file.is_directory && ri->local_uri[uri_len - 1] != '/') {
10111      gmt_time_string(date, sizeof(date), &curtime);
10112      mg_printf(conn,
10113                "HTTP/1.1 301 Moved Permanently\r\n"
10114                "Location: %s/\r\n"
10115                "Date: %s\r\n"
10116                /* "Cache-Control: private\r\n" (= default) */
10117                "Content-Length: 0\r\n"
10118                "Connection: %s\r\n\r\n",
10119                ri->request_uri,
10120                date,
10121                suggest_connection_header(conn));
10122      return;
10123    }
10124
10125    /* 13. Handle other methods than GET/HEAD */
10126    /* 13.1. Handle PROPFIND */
10127    if (!strcmp(ri->request_method, "PROPFIND")) {
10128      handle_propfind(conn, path, &file);
10129      return;
10130    }
10131    /* 13.2. Handle OPTIONS for files */
10132    if (!strcmp(ri->request_method, "OPTIONS")) {
10133      /* This standard handler is only used for real files.
10134       * Scripts should support the OPTIONS method themselves, to allow a
10135       * maximum flexibility.
10136       * Lua and CGI scripts may fully support CORS this way (including
10137       * preflights). */
10138      send_options(conn);
10139      return;
10140    }
10141    /* 13.3. everything but GET and HEAD (e.g. POST) */
10142    if (0 != strcmp(ri->request_method, "GET")
10143        && 0 != strcmp(ri->request_method, "HEAD")) {
10144      send_http_error(conn,
10145                      405,
10146                      "%s method not allowed",
10147                      conn->request_info.request_method);
10148      return;
10149    }
10150
10151    /* 14. directories */
10152    if (file.is_directory) {
10153      if (substitute_index_file(conn, path, sizeof(path), &file)) {
10154        /* 14.1. use a substitute file */
10155        /* TODO (high): substitute index may be a script resource.
10156         * define what should be possible in this case. */
10157      } else {
10158        /* 14.2. no substitute file */
10159        if (!mg_strcasecmp(conn->ctx->config[ENABLE_DIRECTORY_LISTING],
10160                           "yes")) {
10161          handle_directory_request(conn, path);
10162        } else {
10163          send_http_error(conn,
10164                          403,
10165                          "%s",
10166                          "Error: Directory listing denied");
10167        }
10168        return;
10169      }
10170    }
10171
10172    handle_file_based_request(conn, path, &file);
10173#endif /* !defined(NO_FILES) */
10174
10175#if 0
10176            /* Perform redirect and auth checks before calling begin_request()
10177             * handler.
10178             * Otherwise, begin_request() would need to perform auth checks and
10179             * redirects. */
10180#endif
10181  }
10182  return;
10183}
10184
10185
10186static void
10187handle_file_based_request(struct mg_connection *conn,
10188                          const char *path,
10189                          struct file *file)
10190{
10191  if (!conn || !conn->ctx) {
10192    return;
10193  }
10194
10195  if (0) {
10196#ifdef USE_LUA
10197  } else if (match_prefix(conn->ctx->config[LUA_SERVER_PAGE_EXTENSIONS],
10198                          strlen(
10199                              conn->ctx->config[LUA_SERVER_PAGE_EXTENSIONS]),
10200                          path) > 0) {
10201    /* Lua server page: an SSI like page containing mostly plain html
10202     * code
10203     * plus some tags with server generated contents. */
10204    handle_lsp_request(conn, path, file, NULL);
10205  } else if (match_prefix(conn->ctx->config[LUA_SCRIPT_EXTENSIONS],
10206                          strlen(conn->ctx->config[LUA_SCRIPT_EXTENSIONS]),
10207                          path) > 0) {
10208    /* Lua in-server module script: a CGI like script used to generate
10209     * the
10210     * entire reply. */
10211    mg_exec_lua_script(conn, path, NULL);
10212#endif
10213#if defined(USE_DUKTAPE)
10214  } else if (match_prefix(conn->ctx->config[DUKTAPE_SCRIPT_EXTENSIONS],
10215                          strlen(
10216                              conn->ctx->config[DUKTAPE_SCRIPT_EXTENSIONS]),
10217                          path) > 0) {
10218    /* Call duktape to generate the page */
10219    mg_exec_duktape_script(conn, path);
10220#endif
10221#if !defined(NO_CGI)
10222  } else if (match_prefix(conn->ctx->config[CGI_EXTENSIONS],
10223                          strlen(conn->ctx->config[CGI_EXTENSIONS]),
10224                          path) > 0) {
10225    /* CGI scripts may support all HTTP methods */
10226    handle_cgi_request(conn, path);
10227#endif /* !NO_CGI */
10228  } else if (match_prefix(conn->ctx->config[SSI_EXTENSIONS],
10229                          strlen(conn->ctx->config[SSI_EXTENSIONS]),
10230                          path) > 0) {
10231    handle_ssi_file_request(conn, path, file);
10232#if !defined(NO_CACHING)
10233  } else if ((!conn->in_error_handler) && is_not_modified(conn, file)) {
10234    /* Send 304 "Not Modified" - this must not send any body data */
10235    send_http_error(conn, 304, "%s", "");
10236#endif /* !NO_CACHING */
10237  } else {
10238    handle_static_file_request(conn, path, file, NULL);
10239  }
10240}
10241
10242
10243static void
10244close_all_listening_sockets(struct mg_context *ctx)
10245{
10246  unsigned int i;
10247  if (!ctx) {
10248    return;
10249  }
10250
10251  for (i = 0; i < ctx->num_listening_sockets; i++) {
10252    closesocket(ctx->listening_sockets[i].sock);
10253    ctx->listening_sockets[i].sock = INVALID_SOCKET;
10254  }
10255  mg_free(ctx->listening_sockets);
10256  ctx->listening_sockets = NULL;
10257  mg_free(ctx->listening_ports);
10258  ctx->listening_ports = NULL;
10259}
10260
10261
10262/* Valid listening port specification is: [ip_address:]port[s]
10263 * Examples for IPv4: 80, 443s, 127.0.0.1:3128, 1.2.3.4:8080s
10264 * Examples for IPv6: [::]:80, [::1]:80,
10265 *   [FEDC:BA98:7654:3210:FEDC:BA98:7654:3210]:443s
10266 *   see https://tools.ietf.org/html/rfc3513#section-2.2 */
10267static int
10268parse_port_string(const struct vec *vec, struct socket *so)
10269{
10270  unsigned int a, b, c, d, port;
10271  int ch, len;
10272#if defined(USE_IPV6)
10273  char buf[100] = {0};
10274#endif
10275
10276  /* MacOS needs that. If we do not zero it, subsequent bind() will fail.
10277   * Also, all-zeroes in the socket address means binding to all addresses
10278   * for both IPv4 and IPv6 (INADDR_ANY and IN6ADDR_ANY_INIT). */
10279  memset(so, 0, sizeof(*so));
10280  so->lsa.sin.sin_family = AF_INET;
10281
10282  if (sscanf(vec->ptr, "%u.%u.%u.%u:%u%n", &a, &b, &c, &d, &port, &len)
10283      == 5) {
10284    /* Bind to a specific IPv4 address, e.g. 192.168.1.5:8080 */
10285    so->lsa.sin.sin_addr.s_addr =
10286        htonl((a << 24) | (b << 16) | (c << 8) | d);
10287    so->lsa.sin.sin_port = htons((uint16_t)port);
10288#if defined(USE_IPV6)
10289  } else if (sscanf(vec->ptr, "[%49[^]]]:%u%n", buf, &port, &len) == 2
10290             && mg_inet_pton(
10291                    AF_INET6, buf, &so->lsa.sin6, sizeof(so->lsa.sin6))) {
10292    /* IPv6 address, examples: see above */
10293    /* so->lsa.sin6.sin6_family = AF_INET6; already set by mg_inet_pton
10294     */
10295    so->lsa.sin6.sin6_port = htons((uint16_t)port);
10296#endif
10297  } else if (sscanf(vec->ptr, "%u%n", &port, &len) == 1) {
10298    /* If only port is specified, bind to IPv4, INADDR_ANY */
10299    so->lsa.sin.sin_port = htons((uint16_t)port);
10300  } else {
10301    /* Parsing failure. Make port invalid. */
10302    port = 0;
10303    len = 0;
10304  }
10305
10306  /* sscanf and the option splitting code ensure the following condition
10307   */
10308  if (
 Recommendations (Experimental)  R1: ((len != {const}) && (len > unsigned->vec.xx_d))
R2: ((len < 0) && (len > unsigned->vec))
R3: ((len < 0) && (len < unsigned->vec.xx_d))
R4: ((len < 0) && (len < unsigned.vec->xx_d))
R5: ((len != 0) && (len > unsigned->len))
 Score  Issue:  1 unfamiliar pattern(s) detected 
Cost: 11.50, Total Score: 1011.50
Class: complex_2
(
len < 0) && ((unsigned)len > (unsigned)vec->len)) {
10309    return 0;
10310  }
10311  ch = vec->ptr[len]; /* Next character after the port number */
10312  so->is_ssl = (ch == 's');
10313  so->ssl_redir = (ch == 'r');
10314
10315  /* Make sure the port is valid and vector ends with 's', 'r' or ',' */
10316  return is_valid_port(port)
10317         && (ch == '\0' || ch == 's' || ch == 'r' || ch == ',');
10318}
10319
10320
10321static int
10322set_ports_option(struct mg_context *ctx)
10323{
10324  const char *list;
10325  int on = 1;
10326#if defined(USE_IPV6)
10327  int off = 0;
10328#endif
10329  struct vec vec;
10330  struct socket so, *ptr;
10331
10332  in_port_t *portPtr;
10333  union usa usa;
10334  socklen_t len;
10335
10336  int portsTotal = 0;
10337  int portsOk = 0;
10338
10339  if (!ctx) {
10340    return 0;
10341  }
10342
10343  memset(&so, 0, sizeof(so));
10344  memset(&usa, 0, sizeof(usa));
10345  len = sizeof(usa);
10346  list = ctx->config[LISTENING_PORTS];
10347  while ((list = next_option(list, &vec, NULL)) != NULL) {
10348
10349    portsTotal++;
10350
10351    if (!parse_port_string(&vec, &so)) {
10352      mg_cry(fc(ctx),
10353             "%.*s: invalid port spec (entry %i). Expecting list of: %s",
10354             (int)vec.len,
10355             vec.ptr,
10356             portsTotal,
10357             "[IP_ADDRESS:]PORT[s|r]");
10358      continue;
10359    }
10360
10361    if (so.is_ssl && ctx->ssl_ctx == NULL) {
10362
10363      mg_cry(fc(ctx),
10364             "Cannot add SSL socket (entry %i). Is -ssl_certificate "
10365             "option set?",
10366             portsTotal);
10367      continue;
10368    }
10369
10370    if ((so.sock = socket(so.lsa.sa.sa_family, SOCK_STREAM, 6))
10371        == INVALID_SOCKET) {
10372
10373      mg_cry(fc(ctx), "cannot create socket (entry %i)", portsTotal);
10374      continue;
10375    }
10376
10377#ifdef _WIN32
10378    /* Windows SO_REUSEADDR lets many procs binds to a
10379     * socket, SO_EXCLUSIVEADDRUSE makes the bind fail
10380     * if someone already has the socket -- DTL */
10381    /* NOTE: If SO_EXCLUSIVEADDRUSE is used,
10382     * Windows might need a few seconds before
10383     * the same port can be used again in the
10384     * same process, so a short Sleep may be
10385     * required between mg_stop and mg_start.
10386     */
10387    if (setsockopt(so.sock,
10388                   SOL_SOCKET,
10389                   SO_EXCLUSIVEADDRUSE,
10390                   (SOCK_OPT_TYPE)&on,
10391                   sizeof(on)) != 0) {
10392
10393      mg_cry(fc(ctx),
10394             "cannot set socket option SO_EXCLUSIVEADDRUSE (entry %i)",
10395             portsTotal);
10396    }
10397#else
10398    if (setsockopt(so.sock,
10399                   SOL_SOCKET,
10400                   SO_REUSEADDR,
10401                   (SOCK_OPT_TYPE)&on,
10402                   sizeof(on)) != 0) {
10403
10404      mg_cry(fc(ctx),
10405             "cannot set socket option SO_REUSEADDR (entry %i)",
10406             portsTotal);
10407    }
10408#endif
10409
10410#if defined(USE_IPV6)
10411    if (so.lsa.sa.sa_family == AF_INET6
10412        && setsockopt(so.sock,
10413                      IPPROTO_IPV6,
10414                      IPV6_V6ONLY,
10415                      (void *)&off,
10416                      sizeof(off)) != 0) {
10417
10418      mg_cry(fc(ctx),
10419             "cannot set socket option IPV6_V6ONLY (entry %i)",
10420             portsTotal);
10421    }
10422#endif
10423
10424    if (so.lsa.sa.sa_family == AF_INET) {
10425
10426      len = sizeof(so.lsa.sin);
10427      if (bind(so.sock, &so.lsa.sa, len) != 0) {
10428        mg_cry(fc(ctx),
10429               "cannot bind to %.*s: %d (%s)",
10430               (int)vec.len,
10431               vec.ptr,
10432               (int)ERRNO,
10433               strerror(errno));
10434        closesocket(so.sock);
10435        so.sock = INVALID_SOCKET;
10436        continue;
10437      }
10438    }
10439#if defined(USE_IPV6)
10440    else if (so.lsa.sa.sa_family == AF_INET6) {
10441
10442      len = sizeof(so.lsa.sin6);
10443      if (bind(so.sock, &so.lsa.sa, len) != 0) {
10444        mg_cry(fc(ctx),
10445               "cannot bind to IPv6 %.*s: %d (%s)",
10446               (int)vec.len,
10447               vec.ptr,
10448               (int)ERRNO,
10449               strerror(errno));
10450        closesocket(so.sock);
10451        so.sock = INVALID_SOCKET;
10452        continue;
10453      }
10454    }
10455#endif
10456    else {
10457      mg_cry(fc(ctx),
10458             "cannot bind: address family not supported (entry %i)",
10459             portsTotal);
10460      continue;
10461    }
10462
10463    if (listen(so.sock, SOMAXCONN) != 0) {
10464
10465      mg_cry(fc(ctx),
10466             "cannot listen to %.*s: %d (%s)",
10467             (int)vec.len,
10468             vec.ptr,
10469             (int)ERRNO,
10470             strerror(errno));
10471      closesocket(so.sock);
10472      so.sock = INVALID_SOCKET;
10473      continue;
10474    }
10475
10476    if (getsockname(so.sock, &(usa.sa), &len) != 0) {
10477
10478      int err = (int)ERRNO;
10479      mg_cry(fc(ctx),
10480             "call to getsockname failed %.*s: %d (%s)",
10481             (int)vec.len,
10482             vec.ptr,
10483             err,
10484             strerror(errno));
10485      closesocket(so.sock);
10486      so.sock = INVALID_SOCKET;
10487      continue;
10488    }
10489
10490    if ((ptr = (struct socket *)
10491             mg_realloc(ctx->listening_sockets,
10492                        (ctx->num_listening_sockets + 1)
10493                            * sizeof(ctx->listening_sockets[0]))) == NULL) {
10494
10495      mg_cry(fc(ctx), "%s", "Out of memory");
10496      closesocket(so.sock);
10497      so.sock = INVALID_SOCKET;
10498      continue;
10499    }
10500
10501    if ((portPtr =
10502             (in_port_t *)mg_realloc(ctx->listening_ports,
10503                                     (ctx->num_listening_sockets + 1)
10504                                         * sizeof(ctx->listening_ports[0])))
10505        == NULL) {
10506
10507      mg_cry(fc(ctx), "%s", "Out of memory");
10508      closesocket(so.sock);
10509      so.sock = INVALID_SOCKET;
10510      mg_free(ptr);
10511      continue;
10512    }
10513
10514    set_close_on_exec(so.sock, fc(ctx));
10515    ctx->listening_sockets = ptr;
10516    ctx->listening_sockets[ctx->num_listening_sockets] = so;
10517    ctx->listening_ports = portPtr;
10518    ctx->listening_ports[ctx->num_listening_sockets] =
10519        ntohs(usa.sin.sin_port);
10520    ctx->num_listening_sockets++;
10521    portsOk++;
10522  }
10523
10524  if (portsOk != portsTotal) {
10525    close_all_listening_sockets(ctx);
10526    portsOk = 0;
10527  }
10528
10529  return portsOk;
10530}
10531
10532
10533static const char *
10534header_val(const struct mg_connection *conn, const char *header)
10535{
10536  const char *header_value;
10537
10538  if ((header_value = mg_get_header(conn, header)) == NULL) {
10539    return "-";
10540  } else {
10541    return header_value;
10542  }
10543}
10544
10545
10546static void
10547log_access(const struct mg_connection *conn)
10548{
10549  const struct mg_request_info *ri;
10550  struct file fi;
10551  char date[64], src_addr[IP_ADDR_STR_LEN];
10552  struct tm *tm;
10553
10554  const char *referer;
10555  const char *user_agent;
10556
10557  char buf[4096];
10558
10559  if (!conn || !conn->ctx) {
10560    return;
10561  }
10562
10563  if (conn->ctx->config[ACCESS_LOG_FILE] != NULL) {
10564    if (mg_fopen(conn, conn->ctx->config[ACCESS_LOG_FILE], "a+", &fi)
10565        == 0) {
10566      fi.fp = NULL;
10567    }
10568  } else {
10569    fi.fp = NULL;
10570  }
10571
10572  if (fi.fp == NULL && conn->ctx->callbacks.log_message == NULL) {
10573    return;
10574  }
10575
10576  tm = localtime(&conn->conn_birth_time);
10577  if (tm != NULL) {
10578    strftime(date, sizeof(date), "%d/%b/%Y:%H:%M:%S %z", tm);
10579  } else {
10580    mg_strlcpy(date, "01/Jan/1970:00:00:00 +0000", sizeof(date));
10581    date[sizeof(date) - 1] = '\0';
10582  }
10583
10584  ri = &conn->request_info;
10585
10586  sockaddr_to_string(src_addr, sizeof(src_addr), &conn->client.rsa);
10587  referer = header_val(conn, "Referer");
10588  user_agent = header_val(conn, "User-Agent");
10589
10590  mg_snprintf(conn,
10591              NULL, /* Ignore truncation in access log */
10592              buf,
10593              sizeof(buf),
10594              "%s - %s [%s] \"%s %s%s%s HTTP/%s\" %d %" INT64_FMT " %s %s",
10595              src_addr,
10596              ri->remote_user == NULL ? "-" : ri->remote_user,
10597              date,
10598              ri->request_method ? ri->request_method : "-",
10599              ri->request_uri ? ri->request_uri : "-",
10600              ri->query_string ? "?" : "",
10601              ri->query_string ? ri->query_string : "",
10602              ri->http_version,
10603              conn->status_code,
10604              conn->num_bytes_sent,
10605              referer,
10606              user_agent);
10607
10608  if (conn->ctx->callbacks.log_access) {
10609    conn->ctx->callbacks.log_access(conn, buf);
10610  }
10611
10612  if (fi.fp) {
10613    flockfile(fi.fp);
10614    fprintf(fi.fp, "%s\n", buf);
10615    fflush(fi.fp);
10616    funlockfile(fi.fp);
10617    mg_fclose(&fi);
10618  }
10619}
10620
10621
10622/* Verify given socket address against the ACL.
10623 * Return -1 if ACL is malformed, 0 if address is disallowed, 1 if allowed.
10624 */
10625static int
10626check_acl(struct mg_context *ctx, uint32_t remote_ip)
10627{
10628  int allowed, flag;
10629  uint32_t net, mask;
10630  struct vec vec;
10631
10632  if (ctx) {
10633    const char *list = ctx->config[ACCESS_CONTROL_LIST];
10634
10635    /* If any ACL is set, deny by default */
10636    allowed = list == NULL ? '+' : '-';
10637
10638    while ((list = next_option(list, &vec, NULL)) != NULL) {
10639      flag = vec.ptr[0];
10640      if ((flag != '+' && flag != '-')
10641          || parse_net(&vec.ptr[1], &net, &mask) == 0) {
10642        mg_cry(fc(ctx),
10643               "%s: subnet must be [+|-]x.x.x.x[/x]",
10644               __func__);
10645        return -1;
10646      }
10647
10648      if (net == (remote_ip & mask)) {
10649        allowed = flag;
10650      }
10651    }
10652
10653    return allowed == '+';
10654  }
10655  return -1;
10656}
10657
10658
10659#if !defined(_WIN32)
10660static int
10661set_uid_option(struct mg_context *ctx)
10662{
10663  struct passwd *pw;
10664  if (ctx) {
10665    const char *uid = ctx->config[RUN_AS_USER];
10666    int success = 0;
10667
10668    if (uid == NULL) {
10669      success = 1;
10670    } else {
10671      if ((pw = getpwnam(uid)) == NULL) {
10672        mg_cry(fc(ctx), "%s: unknown user [%s]", __func__, uid);
10673      } else if (setgid(pw->pw_gid) == -1) {
10674        mg_cry(fc(ctx),
10675               "%s: setgid(%s): %s",
10676               __func__,
10677               uid,
10678               strerror(errno));
10679      } else if (setgroups(0, NULL)) {
10680        mg_cry(fc(ctx),
10681               "%s: setgroups(): %s",
10682               __func__,
10683               strerror(errno));
10684      } else if (setuid(pw->pw_uid) == -1) {
10685        mg_cry(fc(ctx),
10686               "%s: setuid(%s): %s",
10687               __func__,
10688               uid,
10689               strerror(errno));
10690      } else {
10691        success = 1;
10692      }
10693    }
10694
10695    return success;
10696  }
10697  return 0;
10698}
10699#endif /* !_WIN32 */
10700
10701
10702static void
10703tls_dtor(void *key)
10704{
10705  struct mg_workerTLS *tls = (struct mg_workerTLS *)key;
10706  /* key == pthread_getspecific(sTlsKey); */
10707
10708  if (tls) {
10709    if (tls->is_master == 2) {
10710      tls->is_master = -3; /* Mark memory as dead */
10711      mg_free(tls);
10712    }
10713  }
10714  pthread_setspecific(sTlsKey, NULL);
10715}
10716
10717
10718#if !defined(NO_SSL)
10719
10720/* Must be set if sizeof(pthread_t) > sizeof(unsigned long) */
10721static unsigned long
10722ssl_id_callback(void)
10723{
10724#ifdef _WIN32
10725  return GetCurrentThreadId();
10726#else
10727
10728#ifdef __clang__
10729#pragma clang diagnostic push
10730#pragma clang diagnostic ignored "-Wunreachable-code"
10731/* For every compiler, either "sizeof(pthread_t) > sizeof(unsigned long)"
10732 * or not, so one of the two conditions will be unreachable by construction.
10733 * Unfortunately the C standard does not define a way to check this at
10734 * compile time, since the #if preprocessor conditions can not use the sizeof
10735 * operator as an argument. */
10736#endif
10737
10738  if (sizeof(pthread_t) > sizeof(unsigned long)) {
10739    /* This is the problematic case for CRYPTO_set_id_callback:
10740     * The OS pthread_t can not be cast to unsigned long. */
10741    struct mg_workerTLS *tls =
10742        (struct mg_workerTLS *)pthread_getspecific(sTlsKey);
10743    if (tls == NULL) {
10744      /* SSL called from an unknown thread: Create some thread index.
10745       */
10746      tls = (struct mg_workerTLS *)mg_malloc(sizeof(struct mg_workerTLS));
10747      tls->is_master = -2; /* -2 means "3rd party thread" */
10748      tls->thread_idx = (unsigned)mg_atomic_inc(&thread_idx_max);
10749      pthread_setspecific(sTlsKey, tls);
10750    }
10751    return tls->thread_idx;
10752  } else {
10753    /* pthread_t may be any data type, so a simple cast to unsigned long
10754     * can rise a warning/error, depending on the platform.
10755     * Here memcpy is used as an anything-to-anything cast. */
10756    unsigned long ret = 0;
10757    pthread_t t = pthread_self();
10758    memcpy(&ret, &t, sizeof(pthread_t));
10759    return ret;
10760  }
10761
10762#ifdef __clang__
10763#pragma clang diagnostic pop
10764#endif
10765
10766#endif
10767}
10768
10769
10770static int ssl_use_pem_file(struct mg_context *ctx, const char *pem);
10771static const char *ssl_error(void);
10772
10773
10774static int
10775refresh_trust(struct mg_connection *conn)
10776{
10777  static int reload_lock = 0;
10778  static long int data_check = 0;
10779
10780  struct stat cert_buf;
10781  long int t;
10782  char *pem;
10783  int should_verify_peer;
10784
10785  if ((pem = conn->ctx->config[SSL_CERTIFICATE]) == NULL
10786      && conn->ctx->callbacks.init_ssl == NULL) {
10787    return 0;
10788  }
10789
10790  t = data_check;
10791  if (stat(pem, &cert_buf) != -1) {
10792    t = (long int)cert_buf.st_mtime;
10793  }
10794
10795  if (data_check != t) {
10796    data_check = t;
10797
10798    should_verify_peer =
10799        (conn->ctx->config[SSL_DO_VERIFY_PEER] != NULL)
10800        && (mg_strcasecmp(conn->ctx->config[SSL_DO_VERIFY_PEER], "yes")
10801            == 0);
10802
10803    if (should_verify_peer) {
10804      char *ca_path = conn->ctx->config[SSL_CA_PATH];
10805      char *ca_file = conn->ctx->config[SSL_CA_FILE];
10806      if (SSL_CTX_load_verify_locations(conn->ctx->ssl_ctx,
10807                                        ca_file,
10808                                        ca_path) != 1) {
10809        mg_cry(fc(conn->ctx),
10810               "SSL_CTX_load_verify_locations error: %s "
10811               "ssl_verify_peer requires setting "
10812               "either ssl_ca_path or ssl_ca_file. Is any of them "
10813               "present in "
10814               "the .conf file?",
10815               ssl_error());
10816        return 0;
10817      }
10818    }
10819
10820    if (!reload_lock) {
10821      reload_lock = 1;
10822      if (ssl_use_pem_file(conn->ctx, pem) == 0) {
10823        return 0;
10824      }
10825      reload_lock = 0;
10826    }
10827  }
10828  /* lock while cert is reloading */
10829  while (reload_lock) {
10830    sleep(1);
10831  }
10832
10833  return 1;
10834}
10835
10836
10837static pthread_mutex_t *ssl_mutexes;
10838
10839
10840static int
10841sslize(struct mg_connection *conn, SSL_CTX *s, int (*func)(SSL *))
10842{
10843  int ret, err;
10844  int short_trust;
10845
10846  if (!conn) {
10847    return 0;
10848  }
10849
10850  short_trust =
10851      (conn->ctx->config[SSL_SHORT_TRUST] != NULL)
10852      && (mg_strcasecmp(conn->ctx->config[SSL_SHORT_TRUST], "yes") == 0);
10853
10854  if (short_trust) {
10855    int trust_ret = refresh_trust(conn);
10856    if (!trust_ret) {
10857      return trust_ret;
10858    }
10859  }
10860
10861  conn->ssl = SSL_new(s);
10862  if (conn->ssl == NULL) {
10863    return 0;
10864  }
10865
10866  ret = SSL_set_fd(conn->ssl, conn->client.sock);
10867  if (ret != 1) {
10868    err = SSL_get_error(conn->ssl, ret);
10869    (void)err; /* TODO: set some error message */
10870    SSL_free(conn->ssl);
10871    conn->ssl = NULL;
10872    /* maybe not? CRYPTO_cleanup_all_ex_data(); */
10873    /* see
10874     * https://wiki.openssl.org/index.php/Talk:Library_Initialization */
10875    ERR_remove_state(0);
10876    return 0;
10877  }
10878
10879  ret = func(conn->ssl);
10880  if (ret != 1) {
10881    err = SSL_get_error(conn->ssl, ret);
10882    (void)err; /* TODO: set some error message */
10883    SSL_free(conn->ssl);
10884    conn->ssl = NULL;
10885    /* maybe not? CRYPTO_cleanup_all_ex_data(); */
10886    /* see
10887     * https://wiki.openssl.org/index.php/Talk:Library_Initialization */
10888    ERR_remove_state(0);
10889    return 0;
10890  }
10891
10892  return 1;
10893}
10894
10895
10896/* Return OpenSSL error message (from CRYPTO lib) */
10897static const char *
10898ssl_error(void)
10899{
10900  unsigned long err;
10901  err = ERR_get_error();
10902  return err == 0 ? "" : ERR_error_string(err, NULL);
10903}
10904
10905
10906static void
10907ssl_locking_callback(int mode, int mutex_num, const char *file, int line)
10908{
10909  (void)line;
10910  (void)file;
10911
10912  if (mode & 1) {
10913    /* 1 is CRYPTO_LOCK */
10914    (void)pthread_mutex_lock(&ssl_mutexes[mutex_num]);
10915  } else {
10916    (void)pthread_mutex_unlock(&ssl_mutexes[mutex_num]);
10917  }
10918}
10919
10920
10921#if !defined(NO_SSL_DL)
10922static void *
10923load_dll(struct mg_context *ctx, const char *dll_name, struct ssl_func *sw)
10924{
10925  union {
10926    void *p;
10927    void (*fp)(void);
10928  } u;
10929  void *dll_handle;
10930  struct ssl_func *fp;
10931
10932  if ((dll_handle = dlopen(dll_name, RTLD_LAZY)) == NULL) {
10933    mg_cry(fc(ctx), "%s: cannot load %s", __func__, dll_name);
10934    return NULL;
10935  }
10936
10937  for (fp = sw; fp->name != NULL; fp++) {
10938#ifdef _WIN32
10939    /* GetProcAddress() returns pointer to function */
10940    u.fp = (void (*)(void))dlsym(dll_handle, fp->name);
10941#else
10942    /* dlsym() on UNIX returns void *. ISO C forbids casts of data
10943     * pointers to function pointers. We need to use a union to make a
10944     * cast. */
10945    u.p = dlsym(dll_handle, fp->name);
10946#endif /* _WIN32 */
10947    if (u.fp == NULL) {
10948      mg_cry(fc(ctx),
10949             "%s: %s: cannot find %s",
10950             __func__,
10951             dll_name,
10952             fp->name);
10953      dlclose(dll_handle);
10954      return NULL;
10955    } else {
10956      fp->ptr = u.fp;
10957    }
10958  }
10959
10960  return dll_handle;
10961}
10962
10963
10964static void *ssllib_dll_handle;    /* Store the ssl library handle. */
10965static void *cryptolib_dll_handle; /* Store the crypto library handle. */
10966
10967#endif /* NO_SSL_DL */
10968
10969
10970#if defined(SSL_ALREADY_INITIALIZED)
10971static int cryptolib_users = 1; /* Reference counter for crypto library. */
10972#else
10973static int cryptolib_users = 0; /* Reference counter for crypto library. */
10974#endif
10975
10976
10977static int
10978initialize_ssl(struct mg_context *ctx)
10979{
10980  int i;
10981  size_t size;
10982
10983#if !defined(NO_SSL_DL)
10984  if (!cryptolib_dll_handle) {
10985    cryptolib_dll_handle = load_dll(ctx, CRYPTO_LIB, crypto_sw);
10986    if (!cryptolib_dll_handle) {
10987      return 0;
10988    }
10989  }
10990#endif /* NO_SSL_DL */
10991
10992  if (mg_atomic_inc(&cryptolib_users) > 1) {
10993    return 1;
10994  }
10995
10996  /* Initialize locking callbacks, needed for thread safety.
10997   * http://www.openssl.org/support/faq.html#PROG1
10998   */
10999  i = CRYPTO_num_locks();
11000  if (i < 0) {
11001    i = 0;
11002  }
11003  size = sizeof(pthread_mutex_t) * ((size_t)(i));
11004  if ((ssl_mutexes = (pthread_mutex_t *)mg_malloc(size)) == NULL) {
11005    mg_cry(fc(ctx),
11006           "%s: cannot allocate mutexes: %s",
11007           __func__,
11008           ssl_error());
11009    return 0;
11010  }
11011
11012  for (i = 0; i < CRYPTO_num_locks(); i++) {
11013    pthread_mutex_init(&ssl_mutexes[i], &pthread_mutex_attr);
11014  }
11015
11016  CRYPTO_set_locking_callback(&ssl_locking_callback);
11017  CRYPTO_set_id_callback(&ssl_id_callback);
11018
11019  return 1;
11020}
11021
11022
11023static int
11024ssl_use_pem_file(struct mg_context *ctx, const char *pem)
11025{
11026  if (SSL_CTX_use_certificate_file(ctx->ssl_ctx, pem, 1) == 0) {
11027    mg_cry(fc(ctx),
11028           "%s: cannot open certificate file %s: %s",
11029           __func__,
11030           pem,
11031           ssl_error());
11032    return 0;
11033  }
11034
11035  /* could use SSL_CTX_set_default_passwd_cb_userdata */
11036  if (SSL_CTX_use_PrivateKey_file(ctx->ssl_ctx, pem, 1) == 0) {
11037    mg_cry(fc(ctx),
11038           "%s: cannot open private key file %s: %s",
11039           __func__,
11040           pem,
11041           ssl_error());
11042    return 0;
11043  }
11044
11045  if (SSL_CTX_check_private_key(ctx->ssl_ctx) == 0) {
11046    mg_cry(fc(ctx),
11047           "%s: certificate and private key do not match: %s",
11048           __func__,
11049           pem);
11050    return 0;
11051  }
11052
11053  if (SSL_CTX_use_certificate_chain_file(ctx->ssl_ctx, pem) == 0) {
11054    mg_cry(fc(ctx),
11055           "%s: cannot use certificate chain file %s: %s",
11056           __func__,
11057           pem,
11058           ssl_error());
11059    return 0;
11060  }
11061  return 1;
11062}
11063
11064
11065static long
11066ssl_get_protocol(int version_id)
11067{
11068  long ret = SSL_OP_ALL;
11069  if (version_id > 0)
11070    ret |= SSL_OP_NO_SSLv2;
11071  if (version_id > 1)
11072    ret |= SSL_OP_NO_SSLv3;
11073  if (version_id > 2)
11074    ret |= SSL_OP_NO_TLSv1;
11075  if (version_id > 3)
11076    ret |= SSL_OP_NO_TLSv1_1;
11077  return ret;
11078}
11079
11080
11081/* Dynamically load SSL library. Set up ctx->ssl_ctx pointer. */
11082static int
11083set_ssl_option(struct mg_context *ctx)
11084{
11085  const char *pem;
11086  int callback_ret;
11087  int should_verify_peer;
11088  const char *ca_path;
11089  const char *ca_file;
11090  int use_default_verify_paths;
11091  int verify_depth;
11092  time_t now_rt = time(NULL);
11093  struct timespec now_mt;
11094  md5_byte_t ssl_context_id[16];
11095  md5_state_t md5state;
11096  int protocol_ver;
11097
11098  /* If PEM file is not specified and the init_ssl callback
11099   * is not specified, skip SSL initialization. */
11100  if (!ctx) {
11101    return 0;
11102  }
11103  if ((pem = ctx->config[SSL_CERTIFICATE]) == NULL
11104      && ctx->callbacks.init_ssl == NULL) {
11105    return 1;
11106  }
11107
11108  if (!initialize_ssl(ctx)) {
11109    return 0;
11110  }
11111
11112#if !defined(NO_SSL_DL)
11113  if (!ssllib_dll_handle) {
11114    ssllib_dll_handle = load_dll(ctx, SSL_LIB, ssl_sw);
11115    if (!ssllib_dll_handle) {
11116      return 0;
11117    }
11118  }
11119#endif /* NO_SSL_DL */
11120
11121  /* Initialize SSL library */
11122  SSL_library_init();
11123  SSL_load_error_strings();
11124
11125  if ((ctx->ssl_ctx = SSL_CTX_new(SSLv23_server_method())) == NULL) {
11126    mg_cry(fc(ctx), "SSL_CTX_new (server) error: %s", ssl_error());
11127    return 0;
11128  }
11129
11130  SSL_CTX_clear_options(ctx->ssl_ctx,
11131                        SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3 | SSL_OP_NO_TLSv1
11132                            | SSL_OP_NO_TLSv1_1);
11133  protocol_ver = atoi(ctx->config[SSL_PROTOCOL_VERSION]);
11134  SSL_CTX_set_options(ctx->ssl_ctx, ssl_get_protocol(protocol_ver));
11135  SSL_CTX_set_options(ctx->ssl_ctx, SSL_OP_SINGLE_DH_USE);
11136  SSL_CTX_set_ecdh_auto(ctx->ssl_ctx, 1);
11137
11138  /* If a callback has been specified, call it. */
11139  callback_ret =
11140      (ctx->callbacks.init_ssl == NULL)
11141          ? 0
11142          : (ctx->callbacks.init_ssl(ctx->ssl_ctx, ctx->user_data));
11143
11144  /* If callback returns 0, civetweb sets up the SSL certificate.
11145   * If it returns 1, civetweb assumes the calback already did this.
11146   * If it returns -1, initializing ssl fails. */
11147  if (callback_ret < 0) {
11148    mg_cry(fc(ctx), "SSL callback returned error: %i", callback_ret);
11149    return 0;
11150  }
11151  if (callback_ret > 0) {
11152    if (pem != NULL) {
11153      (void)SSL_CTX_use_certificate_chain_file(ctx->ssl_ctx, pem);
11154    }
11155    return 1;
11156  }
11157
11158  /* Use some UID as session context ID. */
11159  md5_init(&md5state);
11160  md5_append(&md5state, (const md5_byte_t *)&now_rt, sizeof(now_rt));
11161  clock_gettime(CLOCK_MONOTONIC, &now_mt);
11162  md5_append(&md5state, (const md5_byte_t *)&now_mt, sizeof(now_mt));
11163  md5_append(&md5state,
11164             (const md5_byte_t *)ctx->config[LISTENING_PORTS],
11165             strlen(ctx->config[LISTENING_PORTS]));
11166  md5_append(&md5state, (const md5_byte_t *)ctx, sizeof(*ctx));
11167  md5_finish(&md5state, ssl_context_id);
11168
11169  SSL_CTX_set_session_id_context(ctx->ssl_ctx,
11170                                 (const unsigned char *)&ssl_context_id,
11171                                 sizeof(ssl_context_id));
11172
11173  if (pem != NULL) {
11174    if (!ssl_use_pem_file(ctx, pem)) {
11175      return 0;
11176    }
11177  }
11178
11179  should_verify_peer =
11180      (ctx->config[SSL_DO_VERIFY_PEER] != NULL)
11181      && (mg_strcasecmp(ctx->config[SSL_DO_VERIFY_PEER], "yes") == 0);
11182
11183  use_default_verify_paths =
11184      (ctx->config[SSL_DEFAULT_VERIFY_PATHS] != NULL)
11185      && (mg_strcasecmp(ctx->config[SSL_DEFAULT_VERIFY_PATHS], "yes") == 0);
11186
11187  if (should_verify_peer) {
11188    ca_path = ctx->config[SSL_CA_PATH];
11189    ca_file = ctx->config[SSL_CA_FILE];
11190    if (SSL_CTX_load_verify_locations(ctx->ssl_ctx, ca_file, ca_path)
11191        != 1) {
11192      mg_cry(fc(ctx),
11193             "SSL_CTX_load_verify_locations error: %s "
11194             "ssl_verify_peer requires setting "
11195             "either ssl_ca_path or ssl_ca_file. Is any of them "
11196             "present in "
11197             "the .conf file?",
11198             ssl_error());
11199      return 0;
11200    }
11201
11202    SSL_CTX_set_verify(ctx->ssl_ctx,
11203                       SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
11204                       NULL);
11205
11206    if (use_default_verify_paths
11207        && SSL_CTX_set_default_verify_paths(ctx->ssl_ctx) != 1) {
11208      mg_cry(fc(ctx),
11209             "SSL_CTX_set_default_verify_paths error: %s",
11210             ssl_error());
11211      return 0;
11212    }
11213
11214    if (ctx->config[SSL_VERIFY_DEPTH]) {
11215      verify_depth = atoi(ctx->config[SSL_VERIFY_DEPTH]);
11216      SSL_CTX_set_verify_depth(ctx->ssl_ctx, verify_depth);
11217    }
11218  }
11219
11220  if (ctx->config[SSL_CIPHER_LIST] != NULL) {
11221    if (SSL_CTX_set_cipher_list(ctx->ssl_ctx, ctx->config[SSL_CIPHER_LIST])
11222        != 1) {
11223      mg_cry(fc(ctx), "SSL_CTX_set_cipher_list error: %s", ssl_error());
11224    }
11225  }
11226
11227  return 1;
11228}
11229
11230
11231static void
11232uninitialize_ssl(struct mg_context *ctx)
11233{
11234  int i;
11235  (void)ctx;
11236
11237  if (mg_atomic_dec(&cryptolib_users) == 0) {
11238
11239    /* Shutdown according to
11240     * https://wiki.openssl.org/index.php/Library_Initialization#Cleanup
11241     * http://stackoverflow.com/questions/29845527/how-to-properly-uninitialize-openssl
11242     */
11243    CRYPTO_set_locking_callback(NULL);
11244    CRYPTO_set_id_callback(NULL);
11245    ENGINE_cleanup();
11246    CONF_modules_unload(1);
11247    ERR_free_strings();
11248    EVP_cleanup();
11249    CRYPTO_cleanup_all_ex_data();
11250    ERR_remove_state(0);
11251
11252    for (i = 0; i < CRYPTO_num_locks(); i++) {
11253      pthread_mutex_destroy(&ssl_mutexes[i]);
11254    }
11255    mg_free(ssl_mutexes);
11256    ssl_mutexes = NULL;
11257  }
11258}
11259#endif /* !NO_SSL */
11260
11261
11262static int
11263set_gpass_option(struct mg_context *ctx)
11264{
11265  if (ctx) {
11266    struct file file = STRUCT_FILE_INITIALIZER;
11267    const char *path = ctx->config[GLOBAL_PASSWORDS_FILE];
11268    if (path != NULL && !mg_stat(fc(ctx), path, &file)) {
11269      mg_cry(fc(ctx), "Cannot open %s: %s", path, strerror(ERRNO));
11270      return 0;
11271    }
11272    return 1;
11273  }
11274  return 0;
11275}
11276
11277
11278static int
11279set_acl_option(struct mg_context *ctx)
11280{
11281  return check_acl(ctx, (uint32_t)0x7f000001UL) != -1;
11282}
11283
11284
11285static void
11286reset_per_request_attributes(struct mg_connection *conn)
11287{
11288  if (!conn) {
11289    return;
11290  }
11291  conn->path_info = NULL;
11292  conn->num_bytes_sent = conn->consumed_content = 0;
11293  conn->status_code = -1;
11294  conn->is_chunked = 0;
11295  conn->must_close = conn->request_len = conn->throttle = 0;
11296  conn->request_info.content_length = -1;
11297  conn->request_info.remote_user = NULL;
11298  conn->request_info.request_method = NULL;
11299  conn->request_info.request_uri = NULL;
11300  conn->request_info.local_uri = NULL;
11301  conn->request_info.uri = NULL; /* TODO: cleanup uri,
11302                                  * local_uri and request_uri */
11303  conn->request_info.http_version = NULL;
11304  conn->request_info.num_headers = 0;
11305  conn->data_len = 0;
11306  conn->chunk_remainder = 0;
11307  conn->internal_error = 0;
11308}
11309
11310
11311static int
11312set_sock_timeout(SOCKET sock, int milliseconds)
11313{
11314  int r0 = 0, r1, r2;
11315
11316#ifdef _WIN32
11317  /* Windows specific */
11318
11319  DWORD tv = (DWORD)milliseconds;
11320
11321#else
11322  /* Linux, ... (not Windows) */
11323
11324  struct timeval tv;
11325
11326/* TCP_USER_TIMEOUT/RFC5482 (http://tools.ietf.org/html/rfc5482):
11327 * max. time waiting for the acknowledged of TCP data before the connection
11328 * will be forcefully closed and ETIMEDOUT is returned to the application.
11329 * If this option is not set, the default timeout of 20-30 minutes is used.
11330*/
11331/* #define TCP_USER_TIMEOUT (18) */
11332
11333#if defined(TCP_USER_TIMEOUT)
11334  unsigned int uto = (unsigned int)milliseconds;
11335  r0 = setsockopt(sock, 6, TCP_USER_TIMEOUT, (const void *)&uto, sizeof(uto));
11336#endif
11337
11338  memset(&tv, 0, sizeof(tv));
11339  tv.tv_sec = milliseconds / 1000;
11340  tv.tv_usec = (milliseconds * 1000) % 1000000;
11341
11342#endif /* _WIN32 */
11343
11344  r1 = setsockopt(
11345      sock, SOL_SOCKET, SO_RCVTIMEO, (SOCK_OPT_TYPE)&tv, sizeof(tv));
11346  r2 = setsockopt(
11347      sock, SOL_SOCKET, SO_SNDTIMEO, (SOCK_OPT_TYPE)&tv, sizeof(tv));
11348
11349  return r0 || r1 || r2;
11350}
11351
11352
11353static int
11354set_tcp_nodelay(SOCKET sock, int nodelay_on)
11355{
11356  if (setsockopt(sock,
11357                 IPPROTO_TCP,
11358                 TCP_NODELAY,
11359                 (SOCK_OPT_TYPE)&nodelay_on,
11360                 sizeof(nodelay_on)) != 0) {
11361    /* Error */
11362    return 1;
11363  }
11364  /* OK */
11365  return 0;
11366}
11367
11368
11369static void
11370close_socket_gracefully(struct mg_connection *conn)
11371{
11372#if defined(_WIN32)
11373  char buf[MG_BUF_LEN];
11374  int n;
11375#endif
11376  struct linger linger;
11377
11378  if (!conn) {
11379    return;
11380  }
11381
11382  /* Set linger option to avoid socket hanging out after close. This
11383   * prevent
11384   * ephemeral port exhaust problem under high QPS. */
11385  linger.l_onoff = 1;
11386  linger.l_linger = 1;
11387
11388  if (setsockopt(conn->client.sock,
11389                 SOL_SOCKET,
11390                 SO_LINGER,
11391                 (char *)&linger,
11392                 sizeof(linger)) != 0) {
11393    mg_cry(conn,
11394           "%s: setsockopt(SOL_SOCKET SO_LINGER) failed: %s",
11395           __func__,
11396           strerror(ERRNO));
11397  }
11398
11399  /* Send FIN to the client */
11400  shutdown(conn->client.sock, SHUT_WR);
11401  set_non_blocking_mode(conn->client.sock);
11402
11403#if defined(_WIN32)
11404  /* Read and discard pending incoming data. If we do not do that and
11405   * close
11406   * the socket, the data in the send buffer may be discarded. This
11407   * behaviour is seen on Windows, when client keeps sending data
11408   * when server decides to close the connection; then when client
11409   * does recv() it gets no data back. */
11410  do {
11411    n = pull(
11412        NULL, conn, buf, sizeof(buf), 1E-10 /* TODO: allow 0 as timeout */);
11413  } while (n > 0);
11414#endif
11415
11416  /* Now we know that our FIN is ACK-ed, safe to close */
11417  closesocket(conn->client.sock);
11418  conn->client.sock = INVALID_SOCKET;
11419}
11420
11421
11422static void
11423close_connection(struct mg_connection *conn)
11424{
11425  if (!conn || !conn->ctx) {
11426    return;
11427  }
11428
11429#if defined(USE_LUA) && defined(USE_WEBSOCKET)
11430  if (conn->lua_websocket_state) {
11431    lua_websocket_close(conn, conn->lua_websocket_state);
11432    conn->lua_websocket_state = NULL;
11433  }
11434#endif
11435
11436  /* call the connection_close callback if assigned */
11437  if ((conn->ctx->callbacks.connection_close != NULL)
11438      && (conn->ctx->context_type == 1)) {
11439    conn->ctx->callbacks.connection_close(conn);
11440  }
11441
11442  mg_lock_connection(conn);
11443
11444  conn->must_close = 1;
11445
11446#ifndef NO_SSL
11447  if (conn->ssl != NULL) {
11448    /* Run SSL_shutdown twice to ensure completly close SSL connection
11449     */
11450    SSL_shutdown(conn->ssl);
11451    SSL_free(conn->ssl);
11452    /* maybe not? CRYPTO_cleanup_all_ex_data(); */
11453    /* see
11454     * https://wiki.openssl.org/index.php/Talk:Library_Initialization */
11455    ERR_remove_state(0);
11456    conn->ssl = NULL;
11457  }
11458#endif
11459  if (conn->client.sock != INVALID_SOCKET) {
11460    close_socket_gracefully(conn);
11461    conn->client.sock = INVALID_SOCKET;
11462  }
11463
11464  mg_unlock_connection(conn);
11465}
11466
11467void
11468mg_close_connection(struct mg_connection *conn)
11469{
11470  struct mg_context *client_ctx = NULL;
11471  unsigned int i;
11472
11473  if (conn == NULL) {
11474    return;
11475  }
11476
11477  if (conn->ctx->context_type == 2) {
11478    client_ctx = conn->ctx;
11479    /* client context: loops must end */
11480    conn->ctx->stop_flag = 1;
11481  }
11482
11483#ifndef NO_SSL
11484  if (conn->client_ssl_ctx != NULL) {
11485    SSL_CTX_free((SSL_CTX *)conn->client_ssl_ctx);
11486  }
11487#endif
11488  close_connection(conn);
11489  if (client_ctx != NULL) {
11490    /* join worker thread and free context */
11491    for (i = 0; i < client_ctx->cfg_worker_threads; i++) {
11492      if (client_ctx->workerthreadids[i] != 0) {
11493        mg_join_thread(client_ctx->workerthreadids[i]);
11494      }
11495    }
11496    mg_free(client_ctx->workerthreadids);
11497    mg_free(client_ctx);
11498    (void)pthread_mutex_destroy(&conn->mutex);
11499    mg_free(conn);
11500  }
11501}
11502
11503
11504static struct mg_connection *
11505mg_connect_client_impl(const struct mg_client_options *client_options,
11506                       int use_ssl,
11507                       char *ebuf,
11508                       size_t ebuf_len)
11509{
11510  static struct mg_context fake_ctx;
11511  struct mg_connection *conn = NULL;
11512  SOCKET sock;
11513  union usa sa;
11514
11515  if (!connect_socket(&fake_ctx,
11516                      client_options->host,
11517                      client_options->port,
11518                      use_ssl,
11519                      ebuf,
11520                      ebuf_len,
11521                      &sock,
11522                      &sa)) {
11523    ;
11524  } else if ((conn = (struct mg_connection *)
11525                  mg_calloc(1, sizeof(*conn) + MAX_REQUEST_SIZE)) == NULL) {
11526    mg_snprintf(NULL,
11527                NULL, /* No truncation check for ebuf */
11528                ebuf,
11529                ebuf_len,
11530                "calloc(): %s",
11531                strerror(ERRNO));
11532    closesocket(sock);
11533#ifndef NO_SSL
11534  } else if (use_ssl
11535             && (conn->client_ssl_ctx = SSL_CTX_new(SSLv23_client_method()))
11536                    == NULL) {
11537    mg_snprintf(NULL,
11538                NULL, /* No truncation check for ebuf */
11539                ebuf,
11540                ebuf_len,
11541                "SSL_CTX_new error");
11542    closesocket(sock);
11543    mg_free(conn);
11544    conn = NULL;
11545#endif /* NO_SSL */
11546
11547  } else {
11548
11549#ifdef USE_IPV6
11550    socklen_t len = (sa.sa.sa_family == AF_INET)
11551                        ? sizeof(conn->client.rsa.sin)
11552                        : sizeof(conn->client.rsa.sin6);
11553    struct sockaddr *psa =
11554        (sa.sa.sa_family == AF_INET)
11555            ? (struct sockaddr *)&(conn->client.rsa.sin)
11556            : (struct sockaddr *)&(conn->client.rsa.sin6);
11557#else
11558    socklen_t len = sizeof(conn->client.rsa.sin);
11559    struct sockaddr *psa = (struct sockaddr *)&(conn->client.rsa.sin);
11560#endif
11561
11562    conn->buf_size = MAX_REQUEST_SIZE;
11563    conn->buf = (char *)(conn + 1);
11564    conn->ctx = &fake_ctx;
11565    conn->client.sock = sock;
11566    conn->client.lsa = sa;
11567
11568    if (getsockname(sock, psa, &len) != 0) {
11569      mg_cry(conn,
11570             "%s: getsockname() failed: %s",
11571             __func__,
11572             strerror(ERRNO));
11573    }
11574
11575    conn->client.is_ssl = use_ssl ? 1 : 0;
11576    (void)pthread_mutex_init(&conn->mutex, &pthread_mutex_attr);
11577
11578#ifndef NO_SSL
11579    if (use_ssl) {
11580      fake_ctx.ssl_ctx = conn->client_ssl_ctx;
11581
11582      /* TODO: Check ssl_verify_peer and ssl_ca_path here.
11583       * SSL_CTX_set_verify call is needed to switch off server
11584       * certificate checking, which is off by default in OpenSSL and
11585       * on in yaSSL. */
11586      /* TODO: SSL_CTX_set_verify(conn->client_ssl_ctx,
11587       * SSL_VERIFY_PEER, verify_ssl_server); */
11588
11589      if (client_options->client_cert) {
11590        if (!ssl_use_pem_file(&fake_ctx, client_options->client_cert)) {
11591          mg_snprintf(NULL,
11592                      NULL, /* No truncation check for ebuf */
11593                      ebuf,
11594                      ebuf_len,
11595                      "Can not use SSL client certificate");
11596          SSL_CTX_free(conn->client_ssl_ctx);
11597          closesocket(sock);
11598          mg_free(conn);
11599          conn = NULL;
11600        }
11601      }
11602
11603      if (client_options->server_cert) {
11604        SSL_CTX_load_verify_locations(conn->client_ssl_ctx,
11605                                      client_options->server_cert,
11606                                      NULL);
11607        SSL_CTX_set_verify(conn->client_ssl_ctx, SSL_VERIFY_PEER, NULL);
11608      } else {
11609        SSL_CTX_set_verify(conn->client_ssl_ctx, SSL_VERIFY_NONE, NULL);
11610      }
11611
11612      if (!sslize(conn, conn->client_ssl_ctx, SSL_connect)) {
11613        mg_snprintf(NULL,
11614                    NULL, /* No truncation check for ebuf */
11615                    ebuf,
11616                    ebuf_len,
11617                    "SSL connection error");
11618        SSL_CTX_free(conn->client_ssl_ctx);
11619        closesocket(sock);
11620        mg_free(conn);
11621        conn = NULL;
11622      }
11623    }
11624#endif
11625  }
11626
11627  return conn;
11628}
11629
11630
11631CIVETWEB_API struct mg_connection *
11632mg_connect_client_secure(const struct mg_client_options *client_options,
11633                         char *error_buffer,
11634                         size_t error_buffer_size)
11635{
11636  return mg_connect_client_impl(client_options,
11637                                1,
11638                                error_buffer,
11639                                error_buffer_size);
11640}
11641
11642
11643struct mg_connection *
11644mg_connect_client(const char *host,
11645                  int port,
11646                  int use_ssl,
11647                  char *error_buffer,
11648                  size_t error_buffer_size)
11649{
11650  struct mg_client_options opts;
11651  memset(&opts, 0, sizeof(opts));
11652  opts.host = host;
11653  opts.port = port;
11654  return mg_connect_client_impl(&opts,
11655                                use_ssl,
11656                                error_buffer,
11657                                error_buffer_size);
11658}
11659
11660
11661static const struct {
11662  const char *proto;
11663  size_t proto_len;
11664  unsigned default_port;
11665} abs_uri_protocols[] = {{"http://", 7, 80},
11666                         {"https://", 8, 443},
11667                         {"ws://", 5, 80},
11668                         {"wss://", 6, 443},
11669                         {NULL, 0, 0}};
11670
11671
11672/* Check if the uri is valid.
11673 * return 0 for invalid uri,
11674 * return 1 for *,
11675 * return 2 for relative uri,
11676 * return 3 for absolute uri without port,
11677 * return 4 for absolute uri with port */
11678static int
11679get_uri_type(const char *uri)
11680{
11681  int i;
11682  char *hostend, *portbegin, *portend;
11683  unsigned long port;
11684
11685  /* According to the HTTP standard
11686   * http://www.w3.org/Protocols/rfc2616/rfc2616-sec5.html#sec5.1.2
11687   * URI can be an asterisk (*) or should start with slash (relative uri),
11688   * or it should start with the protocol (absolute uri). */
11689  if (uri[0] == '*' && uri[1] == '\0') {
11690    /* asterisk */
11691    return 1;
11692  }
11693  if (uri[0] == '/') {
11694    /* relative uri */
11695    return 2;
11696  }
11697
11698  /* It could be an absolute uri: */
11699  /* This function only checks if the uri is valid, not if it is
11700   * addressing the current server. So civetweb can also be used
11701   * as a proxy server. */
11702  for (i = 0; abs_uri_protocols[i].proto != NULL; i++) {
11703    if (mg_strncasecmp(uri,
11704                       abs_uri_protocols[i].proto,
11705                       abs_uri_protocols[i].proto_len) == 0) {
11706
11707      hostend = strchr(uri + abs_uri_protocols[i].proto_len, '/');
11708      if (!hostend) {
11709        return 0;
11710      }
11711      portbegin = strchr(uri + abs_uri_protocols[i].proto_len, ':');
11712      if (!portbegin) {
11713        return 3;
11714      }
11715
11716      port = strtoul(portbegin + 1, &portend, 10);
11717      if (
 Recommendations (Experimental)  R1: ((portend != hostend) || !port || !is_valid_port)
R2: ((portend != hostend) || !port || !is_valid_port(xx_e))
R3: ((portend != hostend) || !port || !is_valid_port)
R4: ((portend != hostend) || !port || is_valid_port)
R5: ((portend != hostend->port) || !hostend->is_valid_port || xx_e)
 Score  Issue:  1 unfamiliar pattern(s) detected 
Cost: 7.25, Total Score: 1007.25
Class: complex_2
(
portend != hostend) || !port || !is_valid_port(port)) {
11718        return 0;
11719      }
11720
11721      return 4;
11722    }
11723  }
11724
11725  return 0;
11726}
11727
11728
11729/* Return NULL or the relative uri at the current server */
11730static const char *
11731get_rel_url_at_current_server(const char *uri, const struct mg_connection *conn)
11732{
11733  const char *server_domain;
11734  size_t server_domain_len;
11735  size_t request_domain_len = 0;
11736  unsigned long port = 0;
11737  int i;
11738  const char *hostbegin = NULL;
11739  const char *hostend = NULL;
11740  const char *portbegin;
11741  char *portend;
11742
11743  /* DNS is case insensitive, so use case insensitive string compare here
11744   */
11745  server_domain = conn->ctx->config[AUTHENTICATION_DOMAIN];
11746  if (!server_domain) {
11747    return 0;
11748  }
11749  server_domain_len = strlen(server_domain);
11750  if (!server_domain_len) {
11751    return 0;
11752  }
11753
11754  for (i = 0; abs_uri_protocols[i].proto != NULL; i++) {
11755    if (mg_strncasecmp(uri,
11756                       abs_uri_protocols[i].proto,
11757                       abs_uri_protocols[i].proto_len) == 0) {
11758
11759      hostbegin = uri + abs_uri_protocols[i].proto_len;
11760      hostend = strchr(hostbegin, '/');
11761      if (!hostend) {
11762        return 0;
11763      }
11764      portbegin = strchr(hostbegin, ':');
11765      if ((!portbegin) || (portbegin > hostend)) {
11766        port = abs_uri_protocols[i].default_port;
11767        request_domain_len = (size_t)(hostend - hostbegin);
11768      } else {
11769        port = strtoul(portbegin + 1, &portend, 10);
11770        if (
 Recommendations (Experimental)  R1: ((portend != hostend) || !port || !is_valid_port)
R2: ((portend != hostend) || !port || !is_valid_port(xx_e))
R3: ((portend != hostend) || !port || !is_valid_port)
R4: ((portend != hostend) || !port || is_valid_port)
R5: ((portend != hostend->port) || !hostend->is_valid_port || xx_e)
 Score  Issue:  1 unfamiliar pattern(s) detected 
Cost: 7.25, Total Score: 1007.25
Class: complex_2
(
portend != hostend) || !port || !is_valid_port(port)) {
11771          return 0;
11772        }
11773        request_domain_len = (size_t)(portbegin - hostbegin);
11774      }
11775      /* protocol found, port set */
11776      break;
11777    }
11778  }
11779
11780  if (!port) {
11781    /* port remains 0 if the protocol is not found */
11782    return 0;
11783  }
11784
11785#if defined(USE_IPV6)
11786  if (conn->client.lsa.sa.sa_family == AF_INET6) {
11787    if (ntohs(conn->client.lsa.sin6.sin6_port) != port) {
11788      /* Request is directed to a different port */
11789      return 0;
11790    }
11791  } else
11792#endif
11793  {
11794    if (ntohs(conn->client.lsa.sin.sin_port) != port) {
11795      /* Request is directed to a different port */
11796      return 0;
11797    }
11798  }
11799
11800  if ((request_domain_len != server_domain_len)
11801      || (0 != memcmp(server_domain, hostbegin, server_domain_len))) {
11802    /* Request is directed to another server */
11803    return 0;
11804  }
11805
11806  return hostend;
11807}
11808
11809
11810static int
11811getreq(struct mg_connection *conn, char *ebuf, size_t ebuf_len, int *err)
11812{
11813  const char *cl;
11814
11815  if (ebuf_len > 0) {
11816    ebuf[0] = '\0';
11817  }
11818  *err = 0;
11819
11820  reset_per_request_attributes(conn);
11821
11822  if (!conn) {
11823    mg_snprintf(conn,
11824                NULL, /* No truncation check for ebuf */
11825                ebuf,
11826                ebuf_len,
11827                "%s",
11828                "Internal error");
11829    *err = 500;
11830    return 0;
11831  }
11832  /* Set the time the request was received. This value should be used for
11833   * timeouts. */
11834  clock_gettime(CLOCK_MONOTONIC, &(conn->req_time));
11835
11836  conn->request_len =
11837      read_request(NULL, conn, conn->buf, conn->buf_size, &conn->data_len);
11838  /* assert(conn->request_len < 0 || conn->data_len >= conn->request_len);
11839   */
11840  if (conn->request_len >= 0 && conn->data_len < conn->request_len) {
11841    mg_snprintf(conn,
11842                NULL, /* No truncation check for ebuf */
11843                ebuf,
11844                ebuf_len,
11845                "%s",
11846                "Invalid request size");
11847    *err = 500;
11848    return 0;
11849  }
11850
11851  if (conn->request_len == 0 && conn->data_len == conn->buf_size) {
11852    mg_snprintf(conn,
11853                NULL, /* No truncation check for ebuf */
11854                ebuf,
11855                ebuf_len,
11856                "%s",
11857                "Request Too Large");
11858    *err = 413;
11859    return 0;
11860  } else if (conn->request_len <= 0) {
11861    if (conn->data_len > 0) {
11862      mg_snprintf(conn,
11863                  NULL, /* No truncation check for ebuf */
11864                  ebuf,
11865                  ebuf_len,
11866                  "%s",
11867                  "Client sent malformed request");
11868      *err = 400;
11869    } else {
11870      /* Server did not send anything -> just close the connection */
11871      conn->must_close = 1;
11872      mg_snprintf(conn,
11873                  NULL, /* No truncation check for ebuf */
11874                  ebuf,
11875                  ebuf_len,
11876                  "%s",
11877                  "Client did not send a request");
11878      *err = 0;
11879    }
11880    return 0;
11881  } else if (parse_http_message(conn->buf,
11882                                conn->buf_size,
11883                                &conn->request_info) <= 0) {
11884    mg_snprintf(conn,
11885                NULL, /* No truncation check for ebuf */
11886                ebuf,
11887                ebuf_len,
11888                "%s",
11889                "Bad Request");
11890    *err = 400;
11891    return 0;
11892  } else {
11893    /* Message is a valid request or response */
11894    if ((cl = get_header(&conn->request_info, "Content-Length")) != NULL) {
11895      /* Request/response has content length set */
11896      char *endptr = NULL;
11897      conn->content_len = strtoll(cl, &endptr, 10);
11898      if (endptr == cl) {
11899        mg_snprintf(conn,
11900                    NULL, /* No truncation check for ebuf */
11901                    ebuf,
11902                    ebuf_len,
11903                    "%s",
11904                    "Bad Request");
11905        *err = 411;
11906        return 0;
11907      }
11908      /* Publish the content length back to the request info. */
11909      conn->request_info.content_length = conn->content_len;
11910    } else if ((cl = get_header(&conn->request_info, "Transfer-Encoding"))
11911                   != NULL
11912               && !mg_strcasecmp(cl, "chunked")) {
11913      conn->is_chunked = 1;
11914    } else if (!mg_strcasecmp(conn->request_info.request_method, "POST")
11915               || !mg_strcasecmp(conn->request_info.request_method,
11916                                 "PUT")) {
11917      /* POST or PUT request without content length set */
11918      conn->content_len = -1;
11919    } else if (!mg_strncasecmp(conn->request_info.request_method,
11920                               "HTTP/",
11921                               5)) {
11922      /* Response without content length set */
11923      conn->content_len = -1;
11924    } else {
11925      /* Other request */
11926      conn->content_len = 0;
11927    }
11928  }
11929  return 1;
11930}
11931
11932
11933int
11934mg_get_response(struct mg_connection *conn,
11935                char *ebuf,
11936                size_t ebuf_len,
11937                int timeout)
11938{
11939  if (conn) {
11940    /* Implementation of API function for HTTP clients */
11941    int err, ret;
11942    struct mg_context *octx = conn->ctx;
11943    struct mg_context rctx = *(conn->ctx);
11944    char txt[32]; /* will not overflow */
11945
11946    if (timeout >= 0) {
11947      mg_snprintf(conn, NULL, txt, sizeof(txt), "%i", timeout);
11948      rctx.config[REQUEST_TIMEOUT] = txt;
11949      set_sock_timeout(conn->client.sock, timeout);
11950    } else {
11951      rctx.config[REQUEST_TIMEOUT] = NULL;
11952    }
11953
11954    conn->ctx = &rctx;
11955    ret = getreq(conn, ebuf, ebuf_len, &err);
11956    conn->ctx = octx;
11957
11958    /* TODO: 1) uri is deprecated;
11959     *       2) here, ri.uri is the http response code */
11960    conn->request_info.uri = conn->request_info.request_uri;
11961
11962    /* TODO (mid): Define proper return values - maybe return length?
11963     * For the first test use <0 for error and >0 for OK */
11964    return (ret == 0) ? -1 : +1;
11965  }
11966  return -1;
11967}
11968
11969
11970struct mg_connection *
11971mg_download(const char *host,
11972            int port,
11973            int use_ssl,
11974            char *ebuf,
11975            size_t ebuf_len,
11976            const char *fmt,
11977            ...)
11978{
11979  struct mg_connection *conn;
11980  va_list ap;
11981  int i;
11982  int reqerr;
11983
11984  va_start(ap, fmt);
11985  ebuf[0] = '\0';
11986
11987  /* open a connection */
11988  conn = mg_connect_client(host, port, use_ssl, ebuf, ebuf_len);
11989
11990  if (conn != NULL) {
11991    i = mg_vprintf(conn, fmt, ap);
11992    if (i <= 0) {
11993      mg_snprintf(conn,
11994                  NULL, /* No truncation check for ebuf */
11995                  ebuf,
11996                  ebuf_len,
11997                  "%s",
11998                  "Error sending request");
11999    } else {
12000      getreq(conn, ebuf, ebuf_len, &reqerr);
12001
12002      /* TODO: 1) uri is deprecated;
12003       *       2) here, ri.uri is the http response code */
12004      conn->request_info.uri = conn->request_info.request_uri;
12005    }
12006  }
12007
12008  /* if an error occured, close the connection */
12009  if (ebuf[0] != '\0' && conn != NULL) {
12010    mg_close_connection(conn);
12011    conn = NULL;
12012  }
12013
12014  va_end(ap);
12015  return conn;
12016}
12017
12018
12019struct websocket_client_thread_data {
12020  struct mg_connection *conn;
12021  mg_websocket_data_handler data_handler;
12022  mg_websocket_close_handler close_handler;
12023  void *callback_data;
12024};
12025
12026
12027#if defined(USE_WEBSOCKET)
12028#ifdef _WIN32
12029static unsigned __stdcall websocket_client_thread(void *data)
12030#else
12031static void *
12032websocket_client_thread(void *data)
12033#endif
12034{
12035  struct websocket_client_thread_data *cdata =
12036      (struct websocket_client_thread_data *)data;
12037
12038  mg_set_thread_name("ws-client");
12039
12040  if (cdata->conn->ctx) {
12041    if (cdata->conn->ctx->callbacks.init_thread) {
12042      /* 3 indicates a websocket client thread */
12043      /* TODO: check if conn->ctx can be set */
12044      cdata->conn->ctx->callbacks.init_thread(cdata->conn->ctx, 3);
12045    }
12046  }
12047
12048  read_websocket(cdata->conn, cdata->data_handler, cdata->callback_data);
12049
12050  DEBUG_TRACE("%s", "Websocket client thread exited\n");
12051
12052  if (cdata->close_handler != NULL) {
12053    cdata->close_handler(cdata->conn, cdata->callback_data);
12054  }
12055
12056  mg_free((void *)cdata);
12057
12058#ifdef _WIN32
12059  return 0;
12060#else
12061  return NULL;
12062#endif
12063}
12064#endif
12065
12066
12067struct mg_connection *
12068mg_connect_websocket_client(const char *host,
12069                            int port,
12070                            int use_ssl,
12071                            char *error_buffer,
12072                            size_t error_buffer_size,
12073                            const char *path,
12074                            const char *origin,
12075                            mg_websocket_data_handler data_func,
12076                            mg_websocket_close_handler close_func,
12077                            void *user_data)
12078{
12079  struct mg_connection *conn = NULL;
12080
12081#if defined(USE_WEBSOCKET)
12082  struct mg_context *newctx = NULL;
12083  struct websocket_client_thread_data *thread_data;
12084  static const char *magic = "x3JJHMbDL1EzLkh9GBhXDw==";
12085  static const char *handshake_req;
12086
12087  if (origin != NULL) {
12088    handshake_req = "GET %s HTTP/1.1\r\n"
12089                    "Host: %s\r\n"
12090                    "Upgrade: websocket\r\n"
12091                    "Connection: Upgrade\r\n"
12092                    "Sec-WebSocket-Key: %s\r\n"
12093                    "Sec-WebSocket-Version: 13\r\n"
12094                    "Origin: %s\r\n"
12095                    "\r\n";
12096  } else {
12097    handshake_req = "GET %s HTTP/1.1\r\n"
12098                    "Host: %s\r\n"
12099                    "Upgrade: websocket\r\n"
12100                    "Connection: Upgrade\r\n"
12101                    "Sec-WebSocket-Key: %s\r\n"
12102                    "Sec-WebSocket-Version: 13\r\n"
12103                    "\r\n";
12104  }
12105
12106  /* Establish the client connection and request upgrade */
12107  conn = mg_download(host,
12108                     port,
12109                     use_ssl,
12110                     error_buffer,
12111                     error_buffer_size,
12112                     handshake_req,
12113                     path,
12114                     host,
12115                     magic,
12116                     origin);
12117
12118  /* Connection object will be null if something goes wrong */
12119  if (conn == NULL || (strcmp(conn->request_info.request_uri, "101") != 0)) {
12120    if (!*error_buffer) {
12121      /* if there is a connection, but it did not return 101,
12122       * error_buffer is not yet set */
12123      mg_snprintf(conn,
12124                  NULL, /* No truncation check for ebuf */
12125                  error_buffer,
12126                  error_buffer_size,
12127                  "Unexpected server reply");
12128    }
12129    DEBUG_TRACE("Websocket client connect error: %s\r\n", error_buffer);
12130    if (conn != NULL) {
12131      mg_free(conn);
12132      conn = NULL;
12133    }
12134    return conn;
12135  }
12136
12137  /* For client connections, mg_context is fake. Since we need to set a
12138   * callback function, we need to create a copy and modify it. */
12139  newctx = (struct mg_context *)mg_malloc(sizeof(struct mg_context));
12140  memcpy(newctx, conn->ctx, sizeof(struct mg_context));
12141  newctx->user_data = user_data;
12142  newctx->context_type = 2;       /* client context type */
12143  newctx->cfg_worker_threads = 1; /* one worker thread will be created */
12144  newctx->workerthreadids =
12145      (pthread_t *)mg_calloc(newctx->cfg_worker_threads, sizeof(pthread_t));
12146  conn->ctx = newctx;
12147  thread_data = (struct websocket_client_thread_data *)
12148      mg_calloc(sizeof(struct websocket_client_thread_data), 1);
12149  thread_data->conn = conn;
12150  thread_data->data_handler = data_func;
12151  thread_data->close_handler = close_func;
12152  thread_data->callback_data = NULL;
12153
12154  /* Start a thread to read the websocket client connection
12155   * This thread will automatically stop when mg_disconnect is
12156   * called on the client connection */
12157  if (mg_start_thread_with_id(websocket_client_thread,
12158                              (void *)thread_data,
12159                              newctx->workerthreadids) != 0) {
12160    mg_free((void *)thread_data);
12161    mg_free((void *)newctx->workerthreadids);
12162    mg_free((void *)newctx);
12163    mg_free((void *)conn);
12164    conn = NULL;
12165    DEBUG_TRACE("%s",
12166                "Websocket client connect thread could not be started\r\n");
12167  }
12168#else
12169  /* Appease "unused parameter" warnings */
12170  (void)host;
12171  (void)port;
12172  (void)use_ssl;
12173  (void)error_buffer;
12174  (void)error_buffer_size;
12175  (void)path;
12176  (void)origin;
12177  (void)user_data;
12178  (void)data_func;
12179  (void)close_func;
12180#endif
12181
12182  return conn;
12183}
12184
12185
12186static void
12187process_new_connection(struct mg_connection *conn)
12188{
12189  if (conn && conn->ctx) {
12190    struct mg_request_info *ri = &conn->request_info;
12191    int keep_alive_enabled, keep_alive, discard_len;
12192    char ebuf[100];
12193    const char *hostend;
12194    int reqerr, uri_type;
12195
12196    keep_alive_enabled =
12197        !strcmp(conn->ctx->config[ENABLE_KEEP_ALIVE], "yes");
12198
12199    /* Important: on new connection, reset the receiving buffer. Credit
12200     * goes to crule42. */
12201    conn->data_len = 0;
12202    do {
12203      if (!getreq(conn, ebuf, sizeof(ebuf), &reqerr)) {
12204        /* The request sent by the client could not be understood by
12205         * the server, or it was incomplete or a timeout. Send an
12206         * error message and close the connection. */
12207        if (reqerr > 0) {
12208          /*assert(ebuf[0] != '\0');*/
12209          send_http_error(conn, reqerr, "%s", ebuf);
12210        }
12211      } else if (strcmp(ri->http_version, "1.0")
12212                 && strcmp(ri->http_version, "1.1")) {
12213        mg_snprintf(conn,
12214                    NULL, /* No truncation check for ebuf */
12215                    ebuf,
12216                    sizeof(ebuf),
12217                    "Bad HTTP version: [%s]",
12218                    ri->http_version);
12219        send_http_error(conn, 505, "%s", ebuf);
12220      }
12221
12222      if (ebuf[0] == '\0') {
12223        uri_type = get_uri_type(conn->request_info.request_uri);
12224        switch (uri_type) {
12225        case 1:
12226          /* Asterisk */
12227          conn->request_info.local_uri = NULL;
12228          break;
12229        case 2:
12230          /* relative uri */
12231          conn->request_info.local_uri =
12232              conn->request_info.request_uri;
12233          break;
12234        case 3:
12235        case 4:
12236          /* absolute uri (with/without port) */
12237          hostend = get_rel_url_at_current_server(
12238              conn->request_info.request_uri, conn);
12239          if (hostend) {
12240            conn->request_info.local_uri = hostend;
12241          } else {
12242            conn->request_info.local_uri = NULL;
12243          }
12244          break;
12245        default:
12246          mg_snprintf(conn,
12247                      NULL, /* No truncation check for ebuf */
12248                      ebuf,
12249                      sizeof(ebuf),
12250                      "Invalid URI: [%s]",
12251                      ri->request_uri);
12252          send_http_error(conn, 400, "%s", ebuf);
12253          break;
12254        }
12255
12256        /* TODO: cleanup uri, local_uri and request_uri */
12257        conn->request_info.uri = conn->request_info.local_uri;
12258      }
12259
12260      if (ebuf[0] == '\0') {
12261        if (conn->request_info.local_uri) {
12262          /* handle request to local server */
12263          handle_request(conn);
12264          if (conn->ctx->callbacks.end_request != NULL) {
12265            conn->ctx->callbacks.end_request(conn,
12266                                             conn->status_code);
12267          }
12268          log_access(conn);
12269        } else {
12270          /* TODO: handle non-local request (PROXY) */
12271          conn->must_close = 1;
12272        }
12273      } else {
12274        conn->must_close = 1;
12275      }
12276
12277      if (ri->remote_user != NULL) {
12278        mg_free((void *)ri->remote_user);
12279        /* Important! When having connections with and without auth
12280         * would cause double free and then crash */
12281        ri->remote_user = NULL;
12282      }
12283
12284      /* NOTE(lsm): order is important here. should_keep_alive() call
12285       * is
12286       * using parsed request, which will be invalid after memmove's
12287       * below.
12288       * Therefore, memorize should_keep_alive() result now for later
12289       * use
12290       * in loop exit condition. */
12291      keep_alive = conn->ctx->stop_flag == 0 && keep_alive_enabled
12292                   && conn->content_len >= 0 && should_keep_alive(conn);
12293
12294      /* Discard all buffered data for this request */
12295      discard_len = conn->content_len >= 0 && conn->request_len > 0
12296                            && conn->request_len + conn->content_len
12297                                   < (int64_t)conn->data_len
12298                        ? (int)(conn->request_len + conn->content_len)
12299                        : conn->data_len;
12300      /*assert(discard_len >= 0);*/
12301      if (discard_len < 0)
12302        break;
12303      conn->data_len -= discard_len;
12304      if (conn->data_len > 0) {
12305        memmove(conn->buf,
12306                conn->buf + discard_len,
12307                (size_t)conn->data_len);
12308      }
12309
12310      /* assert(conn->data_len >= 0); */
12311      /* assert(conn->data_len <= conn->buf_size); */
12312
12313      if ((conn->data_len < 0) || (conn->data_len > conn->buf_size)) {
12314        break;
12315      }
12316
12317    } while (keep_alive);
12318  }
12319}
12320
12321
12322/* Worker threads take accepted socket from the queue */
12323static int
12324consume_socket(struct mg_context *ctx, struct socket *sp)
12325{
12326#define QUEUE_SIZE(ctx) ((int)(ARRAY_SIZE(ctx->queue)))
12327  if (!ctx) {
12328    return 0;
12329  }
12330
12331  (void)pthread_mutex_lock(&ctx->thread_mutex);
12332  DEBUG_TRACE("%s", "going idle");
12333
12334  /* If the queue is empty, wait. We're idle at this point. */
12335  while (ctx->sq_head == ctx->sq_tail && ctx->stop_flag == 0) {
12336    pthread_cond_wait(&ctx->sq_full, &ctx->thread_mutex);
12337  }
12338
12339  /* If we're stopping, sq_head may be equal to sq_tail. */
12340  if (ctx->sq_head > ctx->sq_tail) {
12341    /* Copy socket from the queue and increment tail */
12342    *sp = ctx->queue[ctx->sq_tail % QUEUE_SIZE(ctx)];
12343    ctx->sq_tail++;
12344
12345    DEBUG_TRACE("grabbed socket %d, going busy", sp ? sp->sock : -1);
12346
12347    /* Wrap pointers if needed */
12348    while (ctx->sq_tail > QUEUE_SIZE(ctx)) {
12349      ctx->sq_tail -= QUEUE_SIZE(ctx);
12350      ctx->sq_head -= QUEUE_SIZE(ctx);
12351    }
12352  }
12353
12354  (void)pthread_cond_signal(&ctx->sq_empty);
12355  (void)pthread_mutex_unlock(&ctx->thread_mutex);
12356
12357  return !ctx->stop_flag;
12358#undef QUEUE_SIZE
12359}
12360
12361
12362static void *
12363worker_thread_run(void *thread_func_param)
12364{
12365  struct mg_context *ctx = (struct mg_context *)thread_func_param;
12366  struct mg_connection *conn;
12367  struct mg_workerTLS tls;
12368#if defined(MG_LEGACY_INTERFACE)
12369  uint32_t addr;
12370#endif
12371
12372  mg_set_thread_name("worker");
12373
12374  tls.is_master = 0;
12375  tls.thread_idx = (unsigned)mg_atomic_inc(&thread_idx_max);
12376#if defined(_WIN32) && !defined(__SYMBIAN32__)
12377  tls.pthread_cond_helper_mutex = CreateEvent(NULL, FALSE, FALSE, NULL);
12378#endif
12379
12380  if (ctx->callbacks.init_thread) {
12381    /* call init_thread for a worker thread (type 1) */
12382    ctx->callbacks.init_thread(ctx, 1);
12383  }
12384
12385  conn =
12386      (struct mg_connection *)mg_calloc(1, sizeof(*conn) + MAX_REQUEST_SIZE);
12387  if (conn == NULL) {
12388    mg_cry(fc(ctx), "%s", "Cannot create new connection struct, OOM");
12389  } else {
12390    pthread_setspecific(sTlsKey, &tls);
12391    conn->buf_size = MAX_REQUEST_SIZE;
12392    conn->buf = (char *)(conn + 1);
12393    conn->ctx = ctx;
12394    conn->request_info.user_data = ctx->user_data;
12395    /* Allocate a mutex for this connection to allow communication both
12396     * within the request handler and from elsewhere in the application
12397     */
12398    (void)pthread_mutex_init(&conn->mutex, &pthread_mutex_attr);
12399
12400    /* Call consume_socket() even when ctx->stop_flag > 0, to let it
12401     * signal sq_empty condvar to wake up the master waiting in
12402     * produce_socket() */
12403    while (consume_socket(ctx, &conn->client)) {
12404      conn->conn_birth_time = time(NULL);
12405
12406/* Fill in IP, port info early so even if SSL setup below fails,
12407 * error handler would have the corresponding info.
12408 * Thanks to Johannes Winkelmann for the patch.
12409 */
12410#if defined(USE_IPV6)
12411      if (conn->client.rsa.sa.sa_family == AF_INET6) {
12412        conn->request_info.remote_port =
12413            ntohs(conn->client.rsa.sin6.sin6_port);
12414      } else
12415#endif
12416      {
12417        conn->request_info.remote_port =
12418            ntohs(conn->client.rsa.sin.sin_port);
12419      }
12420
12421      sockaddr_to_string(conn->request_info.remote_addr,
12422                         sizeof(conn->request_info.remote_addr),
12423                         &conn->client.rsa);
12424
12425#if defined(MG_LEGACY_INTERFACE)
12426      /* This legacy interface only works for the IPv4 case */
12427      addr = ntohl(conn->client.rsa.sin.sin_addr.s_addr);
12428      memcpy(&conn->request_info.remote_ip, &addr, 4);
12429#endif
12430
12431      conn->request_info.is_ssl = conn->client.is_ssl;
12432
12433      if (!conn->client.is_ssl
12434#ifndef NO_SSL
12435          || sslize(conn, conn->ctx->ssl_ctx, SSL_accept)
12436#endif
12437              ) {
12438
12439
12440        process_new_connection(conn);
12441      }
12442
12443      close_connection(conn);
12444    }
12445  }
12446
12447  /* Signal master that we're done with connection and exiting */
12448  (void)pthread_mutex_lock(&ctx->thread_mutex);
12449  ctx->running_worker_threads--;
12450  (void)pthread_cond_signal(&ctx->thread_cond);
12451  /* assert(ctx->running_worker_threads >= 0); */
12452  (void)pthread_mutex_unlock(&ctx->thread_mutex);
12453
12454  pthread_setspecific(sTlsKey, NULL);
12455#if defined(_WIN32) && !defined(__SYMBIAN32__)
12456  CloseHandle(tls.pthread_cond_helper_mutex);
12457#endif
12458  pthread_mutex_destroy(&conn->mutex);
12459  mg_free(conn);
12460
12461  DEBUG_TRACE("%s", "exiting");
12462  return NULL;
12463}
12464
12465
12466/* Threads have different return types on Windows and Unix. */
12467#ifdef _WIN32
12468static unsigned __stdcall worker_thread(void *thread_func_param)
12469{
12470  worker_thread_run(thread_func_param);
12471  return 0;
12472}
12473#else
12474static void *
12475worker_thread(void *thread_func_param)
12476{
12477  worker_thread_run(thread_func_param);
12478  return NULL;
12479}
12480#endif /* _WIN32 */
12481
12482
12483/* Master thread adds accepted socket to a queue */
12484static void
12485produce_socket(struct mg_context *ctx, const struct socket *sp)
12486{
12487#define QUEUE_SIZE(ctx) ((int)(ARRAY_SIZE(ctx->queue)))
12488  if (!ctx) {
12489    return;
12490  }
12491  (void)pthread_mutex_lock(&ctx->thread_mutex);
12492
12493  /* If the queue is full, wait */
12494  while (ctx->stop_flag == 0
12495         && ctx->sq_head - ctx->sq_tail >= QUEUE_SIZE(ctx)) {
12496    (void)pthread_cond_wait(&ctx->sq_empty, &ctx->thread_mutex);
12497  }
12498
12499  if (ctx->sq_head - ctx->sq_tail < QUEUE_SIZE(ctx)) {
12500    /* Copy socket to the queue and increment head */
12501    ctx->queue[ctx->sq_head % QUEUE_SIZE(ctx)] = *sp;
12502    ctx->sq_head++;
12503    DEBUG_TRACE("queued socket %d", sp ? sp->sock : -1);
12504  }
12505
12506  (void)pthread_cond_signal(&ctx->sq_full);
12507  (void)pthread_mutex_unlock(&ctx->thread_mutex);
12508#undef QUEUE_SIZE
12509}
12510
12511
12512static void
12513accept_new_connection(const struct socket *listener, struct mg_context *ctx)
12514{
12515  struct socket so;
12516  char src_addr[IP_ADDR_STR_LEN];
12517  socklen_t len = sizeof(so.rsa);
12518  int on = 1;
12519  int timeout;
12520
12521  if (!listener) {
12522    return;
12523  }
12524
12525  if ((so.sock = accept(listener->sock, &so.rsa.sa, &len))
12526      == INVALID_SOCKET) {
12527  } else if (!check_acl(ctx, ntohl(*(uint32_t *)&so.rsa.sin.sin_addr))) {
12528    sockaddr_to_string(src_addr, sizeof(src_addr), &so.rsa);
12529    mg_cry(fc(ctx), "%s: %s is not allowed to connect", __func__, src_addr);
12530    closesocket(so.sock);
12531    so.sock = INVALID_SOCKET;
12532  } else {
12533    /* Put so socket structure into the queue */
12534    DEBUG_TRACE("Accepted socket %d", (int)so.sock);
12535    set_close_on_exec(so.sock, fc(ctx));
12536    so.is_ssl = listener->is_ssl;
12537    so.ssl_redir = listener->ssl_redir;
12538    if (getsockname(so.sock, &so.lsa.sa, &len) != 0) {
12539      mg_cry(fc(ctx),
12540             "%s: getsockname() failed: %s",
12541             __func__,
12542             strerror(ERRNO));
12543    }
12544
12545    /* Set TCP keep-alive. This is needed because if HTTP-level
12546     * keep-alive
12547     * is enabled, and client resets the connection, server won't get
12548     * TCP FIN or RST and will keep the connection open forever. With
12549     * TCP keep-alive, next keep-alive handshake will figure out that
12550     * the client is down and will close the server end.
12551     * Thanks to Igor Klopov who suggested the patch. */
12552    if (setsockopt(so.sock,
12553                   SOL_SOCKET,
12554                   SO_KEEPALIVE,
12555                   (SOCK_OPT_TYPE)&on,
12556                   sizeof(on)) != 0) {
12557      mg_cry(fc(ctx),
12558             "%s: setsockopt(SOL_SOCKET SO_KEEPALIVE) failed: %s",
12559             __func__,
12560             strerror(ERRNO));
12561    }
12562
12563
12564    /* Disable TCP Nagle's algorithm.  Normally TCP packets are
12565     * coalesced
12566     * to effectively fill up the underlying IP packet payload and
12567     * reduce
12568     * the overhead of sending lots of small buffers. However this hurts
12569     * the server's throughput (ie. operations per second) when HTTP 1.1
12570     * persistent connections are used and the responses are relatively
12571     * small (eg. less than 1400 bytes).
12572     */
12573    if ((ctx != NULL) && (ctx->config[CONFIG_TCP_NODELAY] != NULL)
12574        && (!strcmp(ctx->config[CONFIG_TCP_NODELAY], "1"))) {
12575      if (set_tcp_nodelay(so.sock, 1) != 0) {
12576        mg_cry(fc(ctx),
12577               "%s: setsockopt(IPPROTO_TCP TCP_NODELAY) failed: %s",
12578               __func__,
12579               strerror(ERRNO));
12580      }
12581    }
12582
12583    if (ctx && ctx->config[REQUEST_TIMEOUT]) {
12584      timeout = atoi(ctx->config[REQUEST_TIMEOUT]);
12585    } else {
12586      timeout = -1;
12587    }
12588
12589    /* Set socket timeout to the given value, but not more than a
12590     * a certain limit (SOCKET_TIMEOUT_QUANTUM, default 10 seconds),
12591     * so the server can exit after that time if requested. */
12592    if ((timeout > 0) && (timeout < SOCKET_TIMEOUT_QUANTUM)) {
12593      set_sock_timeout(so.sock, timeout);
12594    } else {
12595      set_sock_timeout(so.sock, SOCKET_TIMEOUT_QUANTUM);
12596    }
12597
12598    produce_socket(ctx, &so);
12599  }
12600}
12601
12602
12603static void
12604master_thread_run(void *thread_func_param)
12605{
12606  struct mg_context *ctx = (struct mg_context *)thread_func_param;
12607  struct mg_workerTLS tls;
12608  struct pollfd *pfd;
12609  unsigned int i;
12610  unsigned int workerthreadcount;
12611
12612  if (!ctx) {
12613    return;
12614  }
12615
12616  mg_set_thread_name("master");
12617
12618/* Increase priority of the master thread */
12619#if defined(_WIN32)
12620  SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_ABOVE_NORMAL);
12621#elif defined(USE_MASTER_THREAD_PRIORITY)
12622  int min_prio = sched_get_priority_min(SCHED_RR);
12623  int max_prio = sched_get_priority_max(SCHED_RR);
12624  if (
 Recommendations (Experimental)  R1: (!(min_prio >= 0 && min_prio <= 0))
R2: (!(min_prio == 123 || min_prio == 123))
R3: (!(min_prio == USE_MASTER_THREAD_PRIORITY && max_prio == "string"))
R4: (!(min_prio == 123 || min_prio == 123 || min_prio == 123))
R5: (!(min_prio == 123 || min_prio == 123 || min_prio == 123 || min_prio == 123))
 Score  Issue:  1 unfamiliar pattern(s) detected 
Cost: 17.75, Total Score: 1017.75
Class: complex_1
(
min_prio >= 0) && (max_prio >= 0)
12625      && ((USE_MASTER_THREAD_PRIORITY) <= max_prio)
12626      && ((USE_MASTER_THREAD_PRIORITY) >= min_prio)) {
12627    struct sched_param sched_param = {0};
12628    sched_param.sched_priority = (USE_MASTER_THREAD_PRIORITY);
12629    pthread_setschedparam(pthread_self(), SCHED_RR, &sched_param);
12630  }
12631#endif
12632
12633/* Initialize thread local storage */
12634#if defined(_WIN32) && !defined(__SYMBIAN32__)
12635  tls.pthread_cond_helper_mutex = CreateEvent(NULL, FALSE, FALSE, NULL);
12636#endif
12637  tls.is_master = 1;
12638  pthread_setspecific(sTlsKey, &tls);
12639
12640  if (ctx->callbacks.init_thread) {
12641    /* Callback for the master thread (type 0) */
12642    ctx->callbacks.init_thread(ctx, 0);
12643  }
12644
12645  /* Server starts *now* */
12646  ctx->start_time = time(NULL);
12647
12648  /* Allocate memory for the listening sockets, and start the server */
12649  pfd =
12650      (struct pollfd *)mg_calloc(ctx->num_listening_sockets, sizeof(pfd[0]));
12651  while (pfd != NULL && ctx->stop_flag == 0) {
12652    for (i = 0; i < ctx->num_listening_sockets; i++) {
12653      pfd[i].fd = ctx->listening_sockets[i].sock;
12654      pfd[i].events = POLLIN;
12655    }
12656
12657    if (poll(pfd, ctx->num_listening_sockets, 200) > 0) {
12658      for (i = 0; i < ctx->num_listening_sockets; i++) {
12659        /* NOTE(lsm): on QNX, poll() returns POLLRDNORM after the
12660         * successful poll, and POLLIN is defined as
12661         * (POLLRDNORM | POLLRDBAND)
12662         * Therefore, we're checking pfd[i].revents & POLLIN, not
12663         * pfd[i].revents == POLLIN. */
12664        if (ctx->stop_flag == 0 && (pfd[i].revents & POLLIN)) {
12665          accept_new_connection(&ctx->listening_sockets[i], ctx);
12666        }
12667      }
12668    }
12669  }
12670  mg_free(pfd);
12671  DEBUG_TRACE("%s", "stopping workers");
12672
12673  /* Stop signal received: somebody called mg_stop. Quit. */
12674  close_all_listening_sockets(ctx);
12675
12676  /* Wakeup workers that are waiting for connections to handle. */
12677  pthread_cond_broadcast(&ctx->sq_full);
12678
12679  /* Wait until all threads finish */
12680  (void)pthread_mutex_lock(&ctx->thread_mutex);
12681  while (ctx->running_worker_threads > 0) {
12682    (void)pthread_cond_wait(&ctx->thread_cond, &ctx->thread_mutex);
12683  }
12684  (void)pthread_mutex_unlock(&ctx->thread_mutex);
12685
12686  /* Join all worker threads to avoid leaking threads. */
12687  workerthreadcount = ctx->cfg_worker_threads;
12688  for (i = 0; i < workerthreadcount; i++) {
12689    if (ctx->workerthreadids[i] != 0) {
12690      mg_join_thread(ctx->workerthreadids[i]);
12691    }
12692  }
12693
12694#if !defined(NO_SSL)
12695  if (ctx->ssl_ctx != NULL) {
12696    uninitialize_ssl(ctx);
12697  }
12698#endif
12699  DEBUG_TRACE("%s", "exiting");
12700
12701#if defined(_WIN32) && !defined(__SYMBIAN32__)
12702  CloseHandle(tls.pthread_cond_helper_mutex);
12703#endif
12704  pthread_setspecific(sTlsKey, NULL);
12705
12706  /* Signal mg_stop() that we're done.
12707   * WARNING: This must be the very last thing this
12708   * thread does, as ctx becomes invalid after this line. */
12709  ctx->stop_flag = 2;
12710}
12711
12712
12713/* Threads have different return types on Windows and Unix. */
12714#ifdef _WIN32
12715static unsigned __stdcall master_thread(void *thread_func_param)
12716{
12717  master_thread_run(thread_func_param);
12718  return 0;
12719}
12720#else
12721static void *
12722master_thread(void *thread_func_param)
12723{
12724  master_thread_run(thread_func_param);
12725  return NULL;
12726}
12727#endif /* _WIN32 */
12728
12729
12730static void
12731free_context(struct mg_context *ctx)
12732{
12733  int i;
12734  struct mg_handler_info *tmp_rh;
12735
12736  if (ctx == NULL) {
12737    return;
12738  }
12739
12740  if (ctx->callbacks.exit_context) {
12741    ctx->callbacks.exit_context(ctx);
12742  }
12743
12744  /* All threads exited, no sync is needed. Destroy thread mutex and
12745   * condvars
12746   */
12747  (void)pthread_mutex_destroy(&ctx->thread_mutex);
12748  (void)pthread_cond_destroy(&ctx->thread_cond);
12749  (void)pthread_cond_destroy(&ctx->sq_empty);
12750  (void)pthread_cond_destroy(&ctx->sq_full);
12751
12752  /* Destroy other context global data structures mutex */
12753  (void)pthread_mutex_destroy(&ctx->nonce_mutex);
12754
12755#if defined(USE_TIMERS)
12756  timers_exit(ctx);
12757#endif
12758
12759  /* Deallocate config parameters */
12760  for (i = 0; i < NUM_OPTIONS; i++) {
12761    if (ctx->config[i] != NULL) {
12762#if defined(_MSC_VER)
12763#pragma warning(suppress : 6001)
12764#endif
12765      mg_free(ctx->config[i]);
12766    }
12767  }
12768
12769  /* Deallocate request handlers */
12770  while (ctx->handlers) {
12771    tmp_rh = ctx->handlers;
12772    ctx->handlers = tmp_rh->next;
12773    mg_free(tmp_rh->uri);
12774    mg_free(tmp_rh);
12775  }
12776
12777#ifndef NO_SSL
12778  /* Deallocate SSL context */
12779  if (ctx->ssl_ctx != NULL) {
12780    SSL_CTX_free(ctx->ssl_ctx);
12781  }
12782#endif /* !NO_SSL */
12783
12784  /* Deallocate worker thread ID array */
12785  if (ctx->workerthreadids != NULL) {
12786    mg_free(ctx->workerthreadids);
12787  }
12788
12789  /* Deallocate the tls variable */
12790  if (mg_atomic_dec(&sTlsInit) == 0) {
12791#if defined(_WIN32) && !defined(__SYMBIAN32__)
12792    DeleteCriticalSection(&global_log_file_lock);
12793#endif /* _WIN32 && !__SYMBIAN32__ */
12794#if !defined(_WIN32)
12795    pthread_mutexattr_destroy(&pthread_mutex_attr);
12796#endif
12797
12798    pthread_key_delete(sTlsKey);
12799  }
12800
12801  /* deallocate system name string */
12802  mg_free(ctx->systemName);
12803
12804  /* Deallocate context itself */
12805  mg_free(ctx);
12806}
12807
12808
12809void
12810mg_stop(struct mg_context *ctx)
12811{
12812  pthread_t mt;
12813  if (!ctx) {
12814    return;
12815  }
12816
12817  /* We don't use a lock here. Calling mg_stop with the same ctx from
12818   * two threads is not allowed. */
12819  mt = ctx->masterthreadid;
12820  if (mt == 0) {
12821    return;
12822  }
12823
12824  ctx->masterthreadid = 0;
12825  ctx->stop_flag = 1;
12826
12827  /* Wait until mg_fini() stops */
12828  while (ctx->stop_flag != 2) {
12829    (void)mg_sleep(10);
12830  }
12831
12832  mg_join_thread(mt);
12833  free_context(ctx);
12834
12835#if defined(_WIN32) && !defined(__SYMBIAN32__)
12836  (void)WSACleanup();
12837#endif /* _WIN32 && !__SYMBIAN32__ */
12838}
12839
12840
12841static void
12842get_system_name(char **sysName)
12843{
12844#if defined(_WIN32)
12845#if !defined(__SYMBIAN32__)
12846  char name[128];
12847  DWORD dwVersion = 0;
12848  DWORD dwMajorVersion = 0;
12849  DWORD dwMinorVersion = 0;
12850  DWORD dwBuild = 0;
12851
12852#ifdef _MSC_VER
12853#pragma warning(push)
12854// GetVersion was declared deprecated
12855#pragma warning(disable : 4996)
12856#endif
12857  dwVersion = GetVersion();
12858#ifdef _MSC_VER
12859#pragma warning(pop)
12860#endif
12861
12862  dwMajorVersion = (DWORD)(LOBYTE(LOWORD(dwVersion)));
12863  dwMinorVersion = (DWORD)(HIBYTE(LOWORD(dwVersion)));
12864  dwBuild = ((dwVersion < 0x80000000) ? (DWORD)(HIWORD(dwVersion)) : 0);
12865  (void)dwBuild;
12866
12867  sprintf(name,
12868          "Windows %u.%u",
12869          (unsigned)dwMajorVersion,
12870          (unsigned)dwMinorVersion);
12871  *sysName = mg_strdup(name);
12872#else
12873  *sysName = mg_strdup("Symbian");
12874#endif
12875#else
12876  struct utsname name;
12877  memset(&name, 0, sizeof(name));
12878  uname(&name);
12879  *sysName = mg_strdup(name.sysname);
12880#endif
12881}
12882
12883
12884struct mg_context *
12885mg_start(const struct mg_callbacks *callbacks,
12886         void *user_data,
12887         const char **options)
12888{
12889  struct mg_context *ctx;
12890  const char *name, *value, *default_value;
12891  int idx, ok, workerthreadcount;
12892  unsigned int i;
12893  void (*exit_callback)(const struct mg_context *ctx) = 0;
12894
12895  struct mg_workerTLS tls;
12896
12897#if defined(_WIN32) && !defined(__SYMBIAN32__)
12898  WSADATA data;
12899  WSAStartup(MAKEWORD(2, 2), &data);
12900#endif /* _WIN32 && !__SYMBIAN32__ */
12901
12902  /* Allocate context and initialize reasonable general case defaults. */
12903  if ((ctx = (struct mg_context *)mg_calloc(1, sizeof(*ctx))) == NULL) {
12904    return NULL;
12905  }
12906
12907  /* Random number generator will initialize at the first call */
12908  ctx->auth_nonce_mask =
12909      (uint64_t)get_random() ^ (uint64_t)(ptrdiff_t)(options);
12910
12911  if (mg_atomic_inc(&sTlsInit) == 1) {
12912
12913#if defined(_WIN32) && !defined(__SYMBIAN32__)
12914    InitializeCriticalSection(&global_log_file_lock);
12915#endif /* _WIN32 && !__SYMBIAN32__ */
12916#if !defined(_WIN32)
12917    pthread_mutexattr_init(&pthread_mutex_attr);
12918    pthread_mutexattr_settype(&pthread_mutex_attr, PTHREAD_MUTEX_RECURSIVE);
12919#endif
12920
12921    if (0 != pthread_key_create(&sTlsKey, tls_dtor)) {
12922      /* Fatal error - abort start. However, this situation should
12923       * never
12924       * occur in practice. */
12925      mg_atomic_dec(&sTlsInit);
12926      mg_cry(fc(ctx), "Cannot initialize thread local storage");
12927      mg_free(ctx);
12928      return NULL;
12929    }
12930  } else {
12931    /* TODO (low): istead of sleeping, check if sTlsKey is already
12932     * initialized. */
12933    mg_sleep(1);
12934  }
12935
12936  tls.is_master = -1;
12937  tls.thread_idx = (unsigned)mg_atomic_inc(&thread_idx_max);
12938#if defined(_WIN32) && !defined(__SYMBIAN32__)
12939  tls.pthread_cond_helper_mutex = NULL;
12940#endif
12941  pthread_setspecific(sTlsKey, &tls);
12942
12943#if defined(USE_LUA)
12944  lua_init_optional_libraries();
12945#endif
12946
12947  ok = 0 == pthread_mutex_init(&ctx->thread_mutex, &pthread_mutex_attr);
12948  ok &= 0 == pthread_cond_init(&ctx->thread_cond, NULL);
12949  ok &= 0 == pthread_cond_init(&ctx->sq_empty, NULL);
12950  ok &= 0 == pthread_cond_init(&ctx->sq_full, NULL);
12951  ok &= 0 == pthread_mutex_init(&ctx->nonce_mutex, &pthread_mutex_attr);
12952  if (!ok) {
12953    /* Fatal error - abort start. However, this situation should never
12954     * occur in practice. */
12955    mg_cry(fc(ctx), "Cannot initialize thread synchronization objects");
12956    mg_free(ctx);
12957    pthread_setspecific(sTlsKey, NULL);
12958    return NULL;
12959  }
12960
12961  if (callbacks) {
12962    ctx->callbacks = *callbacks;
12963    exit_callback = callbacks->exit_context;
12964    ctx->callbacks.exit_context = 0;
12965  }
12966  ctx->user_data = user_data;
12967  ctx->handlers = NULL;
12968
12969#if defined(USE_LUA) && defined(USE_WEBSOCKET)
12970  ctx->shared_lua_websockets = 0;
12971#endif
12972
12973  while (options && (name = *options++) != NULL) {
12974    if ((idx = get_option_index(name)) == -1) {
12975      mg_cry(fc(ctx), "Invalid option: %s", name);
12976      free_context(ctx);
12977      pthread_setspecific(sTlsKey, NULL);
12978      return NULL;
12979    } else if ((value = *options++) == NULL) {
12980      mg_cry(fc(ctx), "%s: option value cannot be NULL", name);
12981      free_context(ctx);
12982      pthread_setspecific(sTlsKey, NULL);
12983      return NULL;
12984    }
12985    if (ctx->config[idx] != NULL) {
12986      mg_cry(fc(ctx), "warning: %s: duplicate option", name);
12987      mg_free(ctx->config[idx]);
12988    }
12989    ctx->config[idx] = mg_strdup(value);
12990    DEBUG_TRACE("[%s] -> [%s]", name, value);
12991  }
12992
12993  /* Set default value if needed */
12994  for (i = 0; config_options[i].name != NULL; i++) {
12995    default_value = config_options[i].default_value;
12996    if (ctx->config[i] == NULL && default_value != NULL) {
12997      ctx->config[i] = mg_strdup(default_value);
12998    }
12999  }
13000
13001#if defined(NO_FILES)
13002  if (ctx->config[DOCUMENT_ROOT] != NULL) {
13003    mg_cry(fc(ctx), "%s", "Document root must not be set");
13004    free_context(ctx);
13005    pthread_setspecific(sTlsKey, NULL);
13006    return NULL;
13007  }
13008#endif
13009
13010  get_system_name(&ctx->systemName);
13011
13012  /* NOTE(lsm): order is important here. SSL certificates must
13013   * be initialized before listening ports. UID must be set last. */
13014  if (!set_gpass_option(ctx) ||
13015#if !defined(NO_SSL)
13016      !set_ssl_option(ctx) ||
13017#endif
13018      !set_ports_option(ctx) ||
13019#if !defined(_WIN32)
13020      !set_uid_option(ctx) ||
13021#endif
13022      !set_acl_option(ctx)) {
13023    free_context(ctx);
13024    pthread_setspecific(sTlsKey, NULL);
13025    return NULL;
13026  }
13027
13028#if !defined(_WIN32) && !defined(__SYMBIAN32__)
13029  /* Ignore SIGPIPE signal, so if browser cancels the request, it
13030   * won't kill the whole process. */
13031  (void)signal(SIGPIPE, SIG_IGN);
13032#endif /* !_WIN32 && !__SYMBIAN32__ */
13033
13034  workerthreadcount = atoi(ctx->config[NUM_THREADS]);
13035
13036  if (workerthreadcount > MAX_WORKER_THREADS) {
13037    mg_cry(fc(ctx), "Too many worker threads");
13038    free_context(ctx);
13039    pthread_setspecific(sTlsKey, NULL);
13040    return NULL;
13041  }
13042
13043  if (workerthreadcount > 0) {
13044    ctx->cfg_worker_threads = ((unsigned int)(workerthreadcount));
13045    ctx->workerthreadids =
13046        (pthread_t *)mg_calloc(ctx->cfg_worker_threads, sizeof(pthread_t));
13047    if (ctx->workerthreadids == NULL) {
13048      mg_cry(fc(ctx), "Not enough memory for worker thread ID array");
13049      free_context(ctx);
13050      pthread_setspecific(sTlsKey, NULL);
13051      return NULL;
13052    }
13053  }
13054
13055#if defined(USE_TIMERS)
13056  if (timers_init(ctx) != 0) {
13057    mg_cry(fc(ctx), "Error creating timers");
13058    free_context(ctx);
13059    pthread_setspecific(sTlsKey, NULL);
13060    return NULL;
13061  }
13062#endif
13063
13064  /* Context has been created - init user libraries */
13065  if (ctx->callbacks.init_context) {
13066    ctx->callbacks.init_context(ctx);
13067  }
13068  ctx->callbacks.exit_context = exit_callback;
13069  ctx->context_type = 1; /* server context */
13070
13071  /* Start master (listening) thread */
13072  mg_start_thread_with_id(master_thread, ctx, &ctx->masterthreadid);
13073
13074  /* Start worker threads */
13075  for (i = 0; i < ctx->cfg_worker_threads; i++) {
13076    (void)pthread_mutex_lock(&ctx->thread_mutex);
13077    ctx->running_worker_threads++;
13078    (void)pthread_mutex_unlock(&ctx->thread_mutex);
13079    if (mg_start_thread_with_id(worker_thread,
13080                                ctx,
13081                                &ctx->workerthreadids[i]) != 0) {
13082      (void)pthread_mutex_lock(&ctx->thread_mutex);
13083      ctx->running_worker_threads--;
13084      (void)pthread_mutex_unlock(&ctx->thread_mutex);
13085      if (i > 0) {
13086        mg_cry(fc(ctx),
13087               "Cannot start worker thread %i: error %ld",
13088               i + 1,
13089               (long)ERRNO);
13090      } else {
13091        mg_cry(fc(ctx),
13092               "Cannot create threads: error %ld",
13093               (long)ERRNO);
13094        free_context(ctx);
13095        pthread_setspecific(sTlsKey, NULL);
13096        return NULL;
13097      }
13098      break;
13099    }
13100  }
13101
13102  pthread_setspecific(sTlsKey, NULL);
13103  return ctx;
13104}
13105
13106
13107/* Feature check API function */
13108unsigned
13109mg_check_feature(unsigned feature)
13110{
13111  static const unsigned feature_set = 0
13112/* Set bits for available features according to API documentation.
13113 * This bit mask is created at compile time, according to the active
13114 * preprocessor defines. It is a single const value at runtime. */
13115#if !defined(NO_FILES)
13116                                      | 0x0001u
13117#endif
13118#if !defined(NO_SSL)
13119                                      | 0x0002u
13120#endif
13121#if !defined(NO_CGI)
13122                                      | 0x0004u
13123#endif
13124#if defined(USE_IPV6)
13125                                      | 0x0008u
13126#endif
13127#if defined(USE_WEBSOCKET)
13128                                      | 0x0010u
13129#endif
13130#if defined(USE_LUA)
13131                                      | 0x0020u
13132#endif
13133#if defined(USE_DUKTAPE)
13134                                      | 0x0040u
13135#endif
13136#if !defined(NO_CACHING)
13137                                      | 0x0080u
13138#endif
13139
13140/* Set some extra bits not defined in the API documentation.
13141 * These bits may change without further notice. */
13142#if defined(MG_LEGACY_INTERFACE)
13143                                      | 0x8000u
13144#endif
13145#if defined(MEMORY_DEBUGGING)
13146                                      | 0x0100u
13147#endif
13148#if defined(USE_TIMERS)
13149                                      | 0x0200u
13150#endif
13151#if !defined(NO_NONCE_CHECK)
13152                                      | 0x0400u
13153#endif
13154#if !defined(NO_POPEN)
13155                                      | 0x0800u
13156#endif
13157      ;
13158  return (feature & feature_set);
13159}